「java.lang.OutOfMemoryError:新しいネイティブスレッドを作成できません」


124

"java.lang.OutOfMemoryError : unable to create new native Thread32Kスレッドの後に8GB RAM VMで「ps-eLF | grep -c java」を取得しています

しかし、"top" and "free -m" shows 50% free memory available。JDkは64ビットで、HotSpotとJRockitの両方で試してみました。サーバーにはLinux 2.6.18が搭載されています

私たちも試しました OS stack size (ulimit -s)微調整と最大プロセス(ulimit -u)制限、limit.confの増加を試みましたが、すべて無駄でした。

また、可能な限りほとんどすべてのヒープサイズの組み合わせを試し、低、高などを維持しました。

アプリケーションの実行に使用するスクリプトは

/opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m -Xss128k -jar JavaNatSimulator.jar /opt/tools/jnatclients/natSimulator.properties

返信いただきありがとうございます。

/etc/security/limits.confとulimitを編集してみましたが、それでも同じです

[root@jboss02 ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 72192
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 72192
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

11
オペレーティングシステムでは、作成できるスレッドの数に制限があります。32k以上のスレッドを作成するのはなぜですか?システムには数千のプロセッサコアがない可能性が高いため、あまり多くのスレッドを作成しても役に立ちません。ExecutorService代わりにスレッドプール()を使用してください。
Jesper 2013年

返信いただきありがとうございます。私たちはオープンソースライブラリを使用しており、それをロードテストしようとしています。そのオープンソースライブラリは非常に多くのスレッドを作成しています。しかし、私が理解できないのは、「トップ」が50%の空きメモリを示しているときであり、なぜOutOfMemoryエラーが発生したのかです。
ディーパックテワニ2013年

我々はICE4jライブラリで使用しているオープンソースライブラリ
ディーパックTewani

11
OutOfMemoryErrorは必ずしもヒープ領域または「一般的な」RAMが使い果たされたことを意味するわけでありませ。この場合、OSに追加のスレッドを割り当てるためのリソースがないために失敗したことが明らかです。50%の空きメモリがあることは、この特定の障害とは無関係です。
Andrzej Doyle

1
新しいスレッドを作成するために必要な他のリソースは何ですか。RAMを増やすと、より多くのスレッドを作成できる可能性があるという印象を受けました。親切にご案内
ディーパックテワニ2013年

回答:


80

これは、例外名が強く示唆しているメモリの問題ではなく、オペレーティングシステムのリソースの問題です。ネイティブスレッドが不足しています。つまり、オペレーティングシステムでJVMが使用できるスレッドの数です。

これはめったに必要ないため、これはまれな問題です。スレッドが終了するはずであるが終了しない場所に無条件のスレッドが大量に発生していますか?

可能であれば、Executorの制御下でCallable / Runnablesを使用するように書き換えることを検討する場合があります。コードで簡単に制御できるさまざまな動作を備えた標準エグゼキューターはたくさんあります。

(スレッドの数が制限される理由はたくさんありますが、それらはオペレーティングシステムによって異なります)


返信いただきありがとうございます。私たちはオープンソースライブラリICE4jを使用しており、それをロードテストしようとしています。サーバーに50%のメモリが残っていることがわかっている場合は、OSのスレッドの制限を増やすことができます。
ディーパックテワニ2013年

たぶん、それだけでは役に立たないと思います。負荷テスト時にリソースが不足した場合は、アプリケーションで発生することを制御できる必要があります。なぜ一度に32000のスレッドがアクティブになるのですか?
–ThorbjørnRavn Andersen 2013

UDPソケットでのデータの読み取りと書き込みに32 Kのスレッドを使用する11Kクライアントを作成しています。これらの32 Kスレッドのうち、10Kスレッドは、ソケットを開いたままにするために使用されるキープアライブスレッドです
Deepak Tewani 2013年

この問題は最新のWebサーバーで解決されると思います。また、udpはパケットを失う可能性があります-Webサーバーを使用しないだけの理由がありますか?
–ThorbjørnRavn Andersen 2013

7
OutOfMemory例外はOutOfResourcesと名付けられているはずだからです。オペレーティングシステムは、必要なリソースを提供できません。(そして、それは私がice4jを知りませんでし判明)
するThorbjörnRavnアンデルセン

14

ロードテスト中に同じ問題が発生しました。理由は、JVMが新しいJavaスレッドをこれ以上作成できないためです。以下はJVMのソースコードです

if (native_thread->osthread() == NULL) {    
// No one should hold a reference to the 'native_thread'.    
    delete native_thread;   
if (JvmtiExport::should_post_resource_exhausted()) {      
    JvmtiExport::post_resource_exhausted(        
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | 
        JVMTI_RESOURCE_EXHAUSTED_THREADS, 
        "unable to create new native thread");    
    } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread");  
} Thread::start(native_thread);`

根本原因:JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR(リソースが使い果たされた(メモリが使い果たされたことを意味する))またはJVMTI_RESOURCE_EXHAUSTED_THREADS(スレッドが使い果たされた)の場合、JVMはこの例外をスローします。

私の場合、Jbossはリクエストを処理するには多すぎるスレッドを作成していますが、すべてのスレッドがブロックされています。このため、JVMはスレッドとメモリを使い果たします(各スレッドはブロックされているため、解放されないメモリを各スレッドが保持します)。

Javaスレッドダンプを分析したところ、61K近くのスレッドが、この問題の原因となっているいずれかの方法によってブロックされていることがわかりました。以下はスレッドダンプの一部です

"SimpleAsyncTaskExecutor-16562" #38070 prio=5 os_prio=0 tid=0x00007f9985440000 nid=0x2ca6 waiting for monitor entry [0x00007f9d58c2d000]
   java.lang.Thread.State: BLOCKED (on object monitor)

メソッドはどのようにブロックされましたか?二度と戻らない?
するThorbjörnRavnアンデルセン

8

OSが、作成しようとしているスレッドの数を許可していないか、JVMで制限に達している可能性があります。特にそれが32kのような丸い数である場合、何らかの種類の制限が原因である可能性が非常に高いです。

本当に32kスレッドが必要ですか?最近のほとんどの言語は、再利用可能なスレッドのプールをなんらかの形でサポートしています。JavaもExecutorService適切な場所にあると思います(ユーザーJesperが述べたように)。おそらく、手動で新しいスレッドを作成する代わりに、そのようなプールからスレッドを要求できます。


1
返信いただきありがとうございます私たちはオープンソースライブラリICE4jを使用しており、それをロードテストしています。サーバーに50%のメモリが残っていることがわかっている場合は、OSのスレッドの制限を増やすことができます。
ディーパックテワニ2013年

1
UDPソケットでのデータの読み取りと書き込みに32 Kのスレッドを使用する11Kクライアントを作成しています。これらの32 Kスレッドのうち、10Kスレッドは、ソケットを開いたままにするために使用されるキープアライブスレッドです
Deepak Tewani 2013年

7

スレッドスタックサイズも確認して、スレッドがさらに作成されるかどうかを確認することをお勧めします。JRockit 1.5 / 1.6のデフォルトのスレッドスタックサイズは、Linux OS上の64ビットVMでは1 MBです。32Kスレッドは、この要件を満たすためにかなりの量の物理メモリと仮想メモリを必要とします。

開始サイズとしてスタックサイズを512 KBに減らし、それがアプリケーションのスレッドの作成に役立つかどうかを確認してください。また、アプリケーションの処理をより多くの物理マシンまたは仮想マシンに分割するなど、水平スケーリングを検討することをお勧めします。

64ビットVMを使用する場合、実際の制限は、OSの物理メモリと仮想メモリの可用性、およびulimitcなどのOSチューニングパラメータによって異なります。以下の記事も参考にしてください。

OutOfMemoryError:新しいネイティブスレッドを作成できません–問題の解​​明


5

jvmがsystemd経由で起動された場合、一部のLinux OSでプロセスごとのmaxTasks制限(タスクは実際にはスレッドを意味する)がある可能性があります。

「サービスステータス」を実行してこれを確認し、maxTasks制限があるかどうかを確認できます。存在する場合は、/ etc / systemd / system.confを編集して、構成を追加することで削除できます。DefaultTasksMax = infinity


3

top in bashを使用すると表示されないゴーストプロセスが原因で同じ問題が発生しました。これにより、JVMはより多くのスレッドを生成できなくなりました。

私にとっては、すべてのJavaプロセスをjpsでリストするときに解決され(jpsシェルで実行するだけ)、それらを使用して個別に強制終了しましたkill -9 pidゴーストプロセスごとにbashコマンドをた

これは、いくつかのシナリオで役立つ場合があります。


2

java.lang.OutOfMemoryError: Unable to create new native threadJVMがOSから新しいスレッドを要求するたびに直面する可能性があります。基盤となるOSが新しいネイティブスレッドを割り当てることができない場合は常に、このOutOfMemoryErrorがスローされます。ネイティブスレッドの正確な制限はプラットフォームに大きく依存するため、以下のリンクの例のようなテストを実行して、これらの制限を見つけることをお勧めします。ただし、一般的に、原因となる状況java.lang.OutOfMemoryError: Unable to create new native threadは次のフェーズを通過します。

  1. JVM内で実行されているアプリケーションによって新しいJavaスレッドが要求された
  2. JVMネイティブコードは、OSに新しいネイティブスレッドを作成する要求をプロキシしますOSは、スレッドにメモリを割り当てる必要がある新しいネイティブスレッドを作成しようとします
  3. 32ビットJavaプロセスサイズがメモリアドレススペースを使い果たした(例:(2-4)GBプロセスサイズの制限に達した)か、OSの仮想メモリが完全に使い果たされたため、OSはネイティブメモリ割り当てを拒否します
  4. java.lang.OutOfMemoryError:Unable to create new native thread errorがスローされます。

リファレンス:https : //plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread


2

スレッドを作成しているプロセスを見つけるには、次のことを試してください。

ps huH

通常、出力をファイルにリダイレクトし、ファイルをオフラインで分析します(各プロセスのスレッド数は期待どおりかどうか)


1

ノードのOutOfMemmoryが原因でジョブが失敗した場合は、最大マップとリデューサーの数、およびそれぞれのJVMの最適化を調整できます。mapred.child.java.opts(デフォルトは200Xmx)は、通常、データノード固有のハードウェアに基づいて増やす必要があります。

このリンクは役に立ちます... pls check


1
私たちはすでに、そのリンクに記載されている変更を試みました。しかし、結果は同じです:(
Deepak Tewani '28

1

JBoss構成にいくつかの問題があります。/opt/jrockit-jdk1.6/bin/java-Xms512m -Xmx512m XmsとXmxは、JBossのメモリ使用量を構成された値に制限しているため、8Gbからサーバーは512Mしか使用していません+自分の目的のためにいくつか追加し、その数を増やし、そこで実行しているOSやその他のもののためにいくつかを空けておくことを忘れないでください。可能であれば、コードを修正するのもよいでしょう。


1

このエラーは、次の2つの理由により発生する可能性があります。

  • 新しいスレッドに対応するためのメモリ領域がありません。

  • スレッドの数がオペレーティングシステムの制限を超えています。

スレッドの数がJavaプロセスの制限を超えていると思います

ですから、おそらく問題はメモリが原因である可能性があります。

スレッドはJVMヒープ内に作成されません。それらは、JVMヒープの外部で作成されます。したがって、RAMに残っているスペースが少ない場合、JVMヒープの割り当て後、アプリケーションは「java.lang.OutOfMemoryError:できない新しいネイティブスレッドを作成できません」に実行されます。

可能な解決策は、ヒープメモリを減らすか、全体的なRAMサイズを増やすことです。


0

これと同じ問題があり、Java APIの不適切な使用であることが判明しました。私は、2回以上初期化されるべきではないバッチ処理メソッドでビルダーを初期化していました。

基本的に私は次のようなことをしていました:

for (batch in batches) {
    process_batch(batch)
}

def process_batch(batch) {
    var client = TransportClient.builder().build()
    client.processList(batch)
}

私がこれをやるべきだったとき:

for (batch in batches) {
    var client = TransportClient.builder().build()
    process_batch(batch, client)
}

def process_batch(batch, client) {
    client.processList(batch)
}

-4

まず第一に、私はOS / VMをそれほど責めたくありません。むしろ、非常に多くのThreadsを作成するコードを書いた開発者です。基本的に、コード(またはサードパーティ)のどこかに、制御なしで多くのスレッドが作成されます。

スタックトレース/コードを注意深く確認し、作成されるスレッドの数を制御します。通常、アプリは大量のスレッドを必要としませんが、それが必要な場合は別の問題です。


10
これは問題の解決策ではありません。
ftrujillo 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.