我正在一個Swing應用程序和最近,我開始看到以下問題:Java GC奇怪的行爲或內存泄漏?
我必須在一個單獨的窗口中顯示一個非常大的工作報告。關閉此窗口,然後重新打開相同的作業報告,並得到OutOfMemory Java堆空間錯誤。
JVM以-Xmx512m啓動,打開作業報告時創建的所有對象在堆上佔用大約300MB。假設沒有內存泄漏,我希望第二次打開相同的作業報告時,JVM不會丟棄OOM。但是,在關閉第一個窗口後查看GC日誌,我沒有看到任何GC活動。
奇怪的是,在關閉第一個窗口後,如果我用jmap進行堆轉儲(沒有「live」選項),仍然可以在堆轉儲中看到對象。
如果我運行轉儲JMAP:現場選項,如下發生:
- 第一堆轉儲拍攝後,我仍然可以看到在堆中的對象。
- 當我拿第二個堆轉儲時,它不再包含那些對象,我可以再次打開相同的作業報告,沒有問題。 因此,如果是內存泄漏,那麼這些對象不可能被收集,對嗎?
我在Java 6(1.6.0_25和1.6.0_45,在Windows上)測試了它,並且它一直在重現。
運行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。 我檢查了OOM被拋出時堆生成的堆轉儲,並且堆長滿了99%,並且沒有任何作業報告對象位於堆上。
在此先感謝。