2013-04-28 42 views
1

我正在一個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%,並且沒有任何作業報告對象位於堆上。

在此先感謝。

回答

1

所以,我的問題是:爲什麼是所有收集的對象,當我走 堆轉儲與實時選項

jmap現場選項強制集合。已經討論過here

您的觀察證實了這一點。

作爲練習可以做些什麼是重新打開窗口發佈一些GC活動以查看內存是否已被回收。