私は Swing アプリケーションに取り組んでいますが、最近、次の問題が発生し始めました。
非常に大きなジョブ レポートを別のウィンドウに表示する必要があります。このウィンドウを閉じてから、同じジョブ レポートを再度開くと、OutOfMemory Java ヒープ スペース エラーが発生します。
JVM は -Xmx512m で開始され、ジョブ レポートを開いたときに作成されるすべてのオブジェクトは、ヒープで約 300MB を使用します。メモリ リークがないと仮定すると、同じジョブ レポートを 2 回目に開いたときに、JVM が OOM をスローしないことが予想されます。しかし、最初のウィンドウを閉じた後に GC ログを見ると、GC アクティビティは見られません。
奇妙なことに、最初のウィンドウを閉じた後、jmap (「ライブ」オプションなし) でヒープ ダンプを取得すると、オブジェクトがまだヒープ ダンプに表示されます。
dump:live オプションを指定して jmap を実行すると、次のことが起こります。
- 最初のヒープ ダンプが取得された後も、ヒープ上のオブジェクトを確認できます。
- 2 番目のヒープ ダンプを取得すると、それらのオブジェクトは含まれなくなり、問題なく同じジョブ レポートを再度開くことができます。メモリ リークだった場合、それらのオブジェクトは収集できなかったのでしょうか。
これを Java 6 (Windows では 1.6.0_25 ad 1.6.0_45) でテストしたところ、常に再現されます。
jmap -heap プリントの実行:
"using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 536870912 (512.0MB)
NewSize = 1048576 (1.0MB)
MaxNewSize = 4294901760 (4095.9375MB)
OldSize = 4194304 (4.0MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 12582912 (12.0MB)
MaxPermSize = 134217728 (128.0MB)
"
JVM は、次のオプションで開始されます。
" -Xms128m
-Xmx512m
-XX:MaxPermSize=128M
-verbose:gc
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-Xloggc:c:\my_gc.log
-XX:+HeapDumpOnOutOfMemoryError"
だから、私の質問は: ライブ オプションでヒープ ダンプを取得するとすべてのオブジェクトが収集されるのはなぜですか (メモリ リークがないことの兆候)。 OOM エラーが発生したため、別の (または同じ) ジョブ レポートを開きますか?
また、別のシナリオをテストしました。
- 最初のジョブ レポート ウィンドウを開いてから閉じます。
- 押されると、JVM が OOM をスローするまで、無限ループで Long インスタンスを作成するメニュー項目を作成しました。OOM がスローされたときに生成されたヒープ ダンプを調べたところ、ヒープは Long インスタンスで 99% 満たされ、ジョブ レポート オブジェクトはヒープ上にありませんでした。
前もって感謝します。