2013-08-01 27 views
5

我正在研究完全用Java編寫的內存數據庫。我們有一個輸入源爲系統提供數據,這是提取/加載階段。當運行這個時,我注意到JVM掛起,根本原因是Full GC被觸發。然後應用程序被凍結,然後出現OutOfMemory錯誤(超出GC開銷限制)負面所需的GC日誌中的倖存者大小

檢查GC日誌顯示出大量垃圾收集,包括年輕人和老年人。 有一件令人驚訝的事情是Desired Survivor的大小是負值。我試圖理解爲什麼這樣呢?有沒有人遇到過這個?

環境:

  • windows7專業服務Pack1
  • 戴爾Precision T7500,24個核心
  • 64位O/S 192 GB RAM

太陽JDK版本: 1.7.0_13-b20(64位)

JVM設置:

  • -Xmx100g
  • -Xms100g
  • -verbose:GC
  • -Xloggc:C:/temp/logs/gc.log
  • -XX :+ PrintGCTimeStamps
  • -XX:+打印詳細清單
  • -XX:+ PrintTenuringDistribution
  • -XX:MaxPermSize參數=256米
  • -XX:+ UseParallelOldGC

GC日誌摘要(這不是完整的日誌):

0.666:[GC 希望的倖存者大小178913280字節,新閾值7(最大15) [PSYoungGen:524289K-> 4431K(30583488K)] 524289K-> 4503K(100488576K),0.0052536秒] [時間:用戶= 0.03 sys = 0.00,實際= 0.01秒]

0.671:[Full GC(系統)[PSYoungGen:4431K-> 0K(30583488K)] [ParOldGen:72K-> 4096K(69905088K)] 4503K-> 4096K(100488576K)[PSPermGen:8852K-> 8847K(21248K)] ,0.0853597秒] [時間:用戶= 0.08 SYS = 0.00,真= 0.09秒]

12.306:[GC 希望的倖存者大小178913280個字節,新的閾值7(最多15) [PSYoungGen:26214464K-> 389676K( 30583488K)] 26218560K-> 393868K(100488576K),0.1907519秒] [時間:用戶= 0.69 SYS = 0.69,真= 0.19秒]

19.845:[GC 希望的倖存者大小178913280個字節,新的閾值7(最多15 ) [PSYoungGen:26604140K-> 4369012K(30583488K)] 26608334K-> 4539738K(100488576K),2。 0671426秒] [Times:user = 12.67 sys = 10.64,real = 2。07秒]

31.930:[GC 希望的倖存者大小178913280個字節,新的閾值7(最多15) [PSYoungGen:30583476K-> 4368998K(30583488K)] 30764447K-> 5793376K(100488576K),2.4316614秒] [時報:用戶= 14.32 SYS = 12.07,實= 2.43秒]

43.950:[GC 希望的倖存者大小178913280個字節,新的閾值7(最多15) [PSYoungGen:30583462K-> 4369018K(30583488K)] 32008283K-> 10474103K(100488576K),3.0868838秒] [時間:用戶= 31.76 sys = 10.64,實際= 3.09秒]

57.851:[GC 所需的倖存者大小e -954466304字節,新閾值6(最大15) [PSYoungGen:30583482K-> 4369011K(16019904K)] 36688571K-> 19053916K(85924992K),5.0616910秒] [時間:用戶= 45.58 sys = 21.95,實際= 5.06秒]

67.849:[GC 希望的倖存者大小-954466304字節,新的閾值5(最多15) [PSYoungGen:16019891K-> 7854065K(23301696K)] 30706222K-> 22540396K(93206784K),1.9574226秒] [時間:用戶= 35.38 SYS = 0.00,真= 1.96秒]

74.940:[GC 希望的倖存者大小-954466304字節,新的閾值4(最多15) [PSYoungGen:19504945K-> 11650800K(23301696K)] 34191281K-> 27450594K (93206784K),3.2089939秒] [Times:user = 54.41 sys = 1.51,實= 3.21秒]

83.683:[GC 希望的倖存者大小-954466304字節,新的閾值3(最多15) [PSYoungGen:23301680K-> 11650785K(23301696K)] 39101518K-> 32434323K(93206784K), 4.8105989秒] [時間:用戶= 65.82 SYS = 10.30,實= 4.81秒]

93.647:[GC 希望的倖存者大小-954466304字節,新的閾值2(最多15) [PSYoungGen:23301665K-> 10083445K( [時間:用戶= 54.77 sys = 8.02,實際= 3.95秒]

102.406:[GC Desi紅色倖存者大小-954466304字節,新閾值1(最大15) [PSYoungGen:21734325K-> 10417779K(23301696K)] 46841988K-> 39667600K(93206784K),4.7031362秒] [時間:用戶= 63.29 sys = 9.50,實際= 4.70秒]

112.109:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15) [PSYoungGen:22068659K-> 5501380K(23301696K)] 51318480K-> 45289996K(93206784K),5.6499475秒] [時報:用戶= 51.39 SYS = 23.81,實= 5.65秒]

122.858:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15) [PSYoungGen:17152260K-> 5829244K(23301696K)] 56941300K- > 51036174K(93206784K),3.9348524秒] [時間S:用戶= 47.49 SYS = 11.48,實= 3.93秒]

132.599:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15) [PSYoungGen:17480124K-> 4411050K(23301696K)] 62703442K - > 55124929K(93206784K),3.2682313秒] [時間:用戶= 35.46 SYS = 10.86,實= 3.27秒]

141.869:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15) [ PSYoungGen:16061930K-> 5983419K(23301696K)] 66775809K-> 61080627K(93206784K),3.1660854sec] [Times:user = 38.39 sys = 9.45,real = 3.17sec]

149。996:[GC 所需倖存者大小-954466304字節,新閾值1(最大15) [PSYoungGen:17634299K-> 5335607K(23301696K)] 72731507K-> 65656597K(93206784K),4.4767380secs] [Times:user = 55.41 sys = 12.67,實= 4.48秒]

154.473:[全GC [PSYoungGen:5335607K-> 0K(23301696K)] [ParOldGen:60320990K-> 29187977K(69905088K)] 65656597K-> 29187977K(93206784K)[PSPermGen:53148K- > 53088K(106560K)],55.6080316秒] [時間:用戶= 518.19 SYS = 3.43,真= 55.61秒]

210.083:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15) [ PSYoungGen:1942K-> 96K(23301696K)] 29189919K-> 29188073K(93206784K),0.0512343秒] [時間:用戶= 0.5 0 SYS = 0.00,真= 0.05秒]

210.134:[全GC [PSYoungGen:96K-> 0K(23301696K)] [ParOldGen:29187977K-> 29187816K(69905088K)] 29188073K-> 29187816K(93206784K)[PSPermGen :53088K-> 53087K(106624K)],15.5128928秒] [時間:用戶= 236.31 SYS = 0.19,真= 15.51秒]

239.525:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15 ) [PSYoungGen:11650880K-> 4622965K(23301696K)] 40838696K-> 33810782K(93206784K),1.2739696秒] [時間:用戶= 23.01 SYS = 0.00,真= 1.27秒]

248.572:[GC 希望的倖存者大小-954466304字節,新的thresh舊1(最大15) [PSYoungGen:16273845K-> 4009690K(23301696K)] 45461663K-> 37894227K(93206784K),2.3307283秒] [時間:用戶= 41.84 SYS = 0.00,真= 2.33秒]

256.854: [GC 所需的倖存者大小-954466304字節,新閾值1(最大15) [PSYoungGen:15660570K-> 5707092K(23301696K)] 49545113K-> 43643553K(93206784K),2.5595566sec] [Times:user = 46.05 sys = 0.00,真實= 2.56秒]

265.471:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15) [PSYoungGen:17357972K-> 4996932K(23301696K)] 55294440K-> 48690372K(93206784K),2.8941178秒] [Times:user = 52.21 sys = 0.00,real = 2.89 secs]

275.795:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15) [PSYoungGen:16647812K-> 3781542K(23301696K)] 60342280K-> 52491436K(93206784K),2.6240427秒] [時間:用戶= 47.18 SYS = 0.00,真= 2.63秒]

284.083:[GC 希望的倖存者大小-954466304字節,新的閾值1(最大15) [PSYoungGen:15432422K-> 5815192K(23301696K)] 64142316K-> 58360954K (93206784K),2.3724770秒] [時間:用戶= 42.68 sys = 0.00,實際= 2.37秒]

291.659:[GC 所需的倖存者大小-954466304由TES,新的閾值1(最大15) [PSYoungGen:17466072K-> 5357588K(23301696K)] 70011840K-> 63780322K(93206784K),3.0063028秒] [時間:用戶= 54.20 SYS = 0.00,真= 3.01秒]

299.322:[GC 所需倖存者大小-1228210176字節,新閾值2(最大15) [PSYoungGen:17008468K-> 6341939K(23301696K)] 75431206K-> 70078817K(93206784K),4.1999305secs] [Times:user = 65.35 sys = 5.13,真= 4.20秒]

303.523:[全GC [PSYoungGen:6341939K-> 0K(23301696K)] [ParOldGen:63736877K-> 38098305K(69905088K)] 70078817K-> 38098305K(93206784K)[PSPermGen:53125K - > 53125K(103360K)],41。2081882秒]

正如你可以注意到在上面的日誌中的57.851秒,我們有一個負所需的倖存者大小,我不知道爲什麼這是這樣嗎?

這看起來像是內存泄漏嗎?

任何幫助將不勝感激。此外,我附上了visualvm堆的快照 Visual VM Heap Snapshot

回答

4

是的,你的問題似乎是,你只是有太多的活的對象。 「超出GC上限」意味着GC運行,需要很長時間並且釋放很少。 有一些旋鈕可以調整來控制閾值,但這些旋鈕無法幫助您提高性能。

我在創建內存密集型模擬(也是100 - 120GB max heap)時遇到了完全相同的問題。 我的解決方案是遠離Objects來存儲數據,並將所有內容都放在基本int []中。工作的 最終變成了一個名爲Banana的新開源項目,該項目支持一些原始數據結構。 香蕉實際上是基於它自己的內存管理上的數據結構,您可以獲得完全動態的數據結構,而不會產生對象的開銷。 繼續閱讀項目wiki,它記錄事情是如何工作的,並獲得示例代碼和基準。

+0

謝謝,是的,這也是我的想法。我注意到JVM在GC壓力下凍結時的另一件事,我拿了堆轉儲,而VisualVM在加載到MAT(Eclipse內存分析器)時可能顯示了50GB的佔用,堆佔用率僅爲10GB左右。這些報告沒有顯示內存泄漏的跡象,所以我也相信它可能是我們正在快速創建大量活動對象。但是當我在MAT中上傳它時,我認爲它具有堆的靜態視圖,並且能夠對可訪問的對象進行一些清理?我會接受你的回答 – Harry

+0

我不確定visualvm和MAT正在報告什麼(我希望他們報告相同的內容),但請記住,Java通常不會告訴你它使用了多少內存。另外 - 如果你使用很多小物體,物體的開銷可能很大。我切換到香蕉數據結構時,一些基準測試顯示內存使用率降低了70%。 –