64 ビット JVM を使用して 64 ビット Windows 7 および Server 2008 を実行しています。使用可能なメモリが十分にあるプログラムで、「java.lang.OutOfMemoryError: 新しいネイティブ スレッドを作成できません」というメッセージが表示されます。私はガベージコレクションやヒープ生成などについて何度も読みましたが、このケースを説明するものは何もないようです. 私が最も近いのは、アイドルスレッドを割り当てるプログラムを提供する1つのエントリです(スレッドを生成してjava.lang.OutOfMemoryErrorをヒットする方法は?Ajay George の応答の下で)、少なくとも製品コードで発生した問題を再現します。問題は、十分な OS メモリ (RAM) が利用可能で、ヒープにほとんど割り当てられていない状態で OOM を取得し、-XX:+HeapDumpOnOutOfMemoryError で実行すると OOM 例外に応答しないことです。小さなヒープ設定 (Xmx16M) と大きなスタック設定 (Xss1G) を使用して上記のコード (アイドル スレッド スポーナー) を実行すると、Java プロセスは失敗する前に約 8179 スレッドを割り当て、タスク マネージャーで表示するとコミット サイズが大きくなります。それよりも、リソースをほとんど要求していません。
私は GC トレースを有効にしましたが、障害が発生する前にごくわずかなアクティビティ (通常は 2 つの GC) を観察しました。PermGen を無駄にブーストしました。初期ヒープ サイズを、障害が発生する前に消費されないポイント (Xms1024M Xmx65536M) まで増やしましたが、それでも OOM が発生します。
YourKit プロファイラーを使用してこれらの両方を調べたところ、ヒープが消費されておらず、GC がほとんど発生していないという、私が疑ったことを正確に示しています。
しかし、私が本番環境で抱えている問題は、失敗したときに約150〜300スレッド(さまざま)しかなく、スタックサイズがデフォルトであるため、Windowsではおそらく1Mです。
私が見つけようとしているのは、コードに適切な変更を加えることができるように、問題の原因を特定する方法です。
メモリ ソースが非常に限られているスレッドを作成するときに、JVM が行う特別なことはありますか? NIO とメモリ マップ ファイルでは、JVM がバックグラウンド メモリ バッキングを追跡せず、メモリ マッピングで高レベルのチャーンがすぐにメモリ不足になることを知っていますが、その場合、OS は JVM によるメモリの使用を示します。 . このスレッドのケースでは、OS は JVM が少量のメモリを使用していると表示します。