2010-02-17 55 views
3

我有一個程序,運行非常愉快-Xmx2g。隨着-Xmx1g,它嘎然而止。它從來沒有得到一個內存不足的例外 - 或者,至少,我從來沒有耐心等待足夠長的時間。平靜興奮的垃圾收集器

這表明總佔地面積符合1g,但GC對空間可能用盡可能會有一些擔憂。內存佔用是一些大型,穩定的項目與大量短暫流量的組合。

是否存在與此情況相關的或多或少晦澀的GC選項?

+6

在那裏,我計劃提供一些關於如何打招呼的提示,並給他們一個關於聖誕節的建議。 – 2010-02-17 01:05:13

+0

@Pekka:請解釋一下...... – JRL 2010-02-17 01:19:16

+0

@JRL他正在考慮駕駛卡車的人。 – bmargulies 2010-02-17 01:29:18

回答

2

在很多情況下,OOME可能需要很長的時間才能完成。這是因爲,當GC開始努力工作時,它會停止程序中的所有活動。如果您通常每得到0.01秒的GC時間即可獲得1秒的有用編程時間,則在這些情況下,您可能會發現它完全相反 - 每隔1s GC時間0.01s的有用編程時間。按照這個速度,吃掉1GB堆的最後512k可能需要很長的時間。

VisualVM及其VisualGC插件是你的朋友;當你處於這種狀態時,它們的圖形將顯示不同的模式。

4

您可以在JVM上爲垃圾收集設置一堆選項,其中http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html。當應用程序由於GC而停下來時,通常會看到許多主要收集,這些收集可能會在收集時停止所有操作。您可以調整次要和主要收集參數,以查看是否可以更頻繁地收集次要信息。

我推薦使用像VisualVM這樣的工具(與JDK6一起發貨,我相信更新7+)來分析這些對象圖表,看看這些堆吃什麼。另請參閱分析hprof文件的工具(How do I analyze a .hprof file?)。

3

這聽起來像你沒有給JVM足夠的堆。當然,工作集可能適合1G字節,但你仍然需要更多。要理解爲什麼,請繼續閱讀。

讓我們假設當一個垃圾收集器運行時,它會執行一定數量的工作W1,它與它掃描以識別垃圾的非垃圾量成正比,而另一工作量W2與它發現的垃圾數量。 (實際上,它比這更復雜一點,但讓我們保持分析簡單。)

假設您有一堆1Gb堆,其中有0.9Gb的堆被可訪問對象佔用。每次GC運行時,它最多可以回收0.1Gb的堆空間,並且這樣做需要執行W1 * 0.9Gb + W2 * 0.1Gb的工作。每字節回收的工作量爲(W1 * 0.9Gb + W2 * 0.1Gb)/0.1Gb;即9 * W1 + W2

現在假設你有一個2Gb堆,其中有0.9Gb被可達對象佔用。現在每個字節回收的工作量是(W1 * 0.9Gb + W2 * 1.1Gb)/1.1GbW1 * 9/11 + W2

如果你比較這兩個,你會發現GC在1Gb堆中回收的每個字節大約需要W1 * 8個字節,與2Gb堆相比。

作爲一般規則,越接近完整地運行堆,垃圾收集器的效率越低。教訓是:

  • 配置爲使用一個慷慨的堆的JVM,並

  • 配置JVM拋出OOM如果小於(比如說)堆的25%自由運行後完整的GC。

+0

只是無法抵抗你的努力 – stacker 2010-02-19 22:59:58