關(guān)于Hotspot TM Java TM虛擬機(jī)中的
垃圾收集的常見(jiàn)問(wèn)題
本文檔描述了 Java( tm ) HotSpot ( tm ) 虛擬機(jī)的行為。但是,此行為不是 VM 規(guī)范的一部分,并且在未來(lái)的版本中可能會(huì)發(fā)生變化。此外,這里描述的 行為是通用行為,并不適用于所有 Java 應(yīng)用程序的執(zhí)行。
1.HotSpot(tm) 中的分代收集器是如何實(shí)現(xiàn)的?
HotSpot 中的默認(rèn)收集器有兩代:年輕代和老年代。大多數(shù)分配都是在年輕一代中完成的。年輕代針對(duì)生命周期相對(duì)于集合之間的間隔較短的對(duì)象進(jìn)行了優(yōu)化。在年輕代中多次收集的對(duì)象被移動(dòng)到終身代。年輕代通常更小,并且被更頻繁地收集。終身代通常較大且收集頻率較低。
年輕代收集器是一個(gè)復(fù)制收集器。年輕代分為 3 個(gè)空間:eden-space、to-space 和 from-space。分配是從 eden-space 和 from-space 完成的。當(dāng)這些已滿時(shí),年輕一代的收集就完成了。期望大多數(shù)對(duì)象都是垃圾,并且任何幸存的對(duì)象都可以復(fù)制到空間。如果存活對(duì)象的數(shù)量超過(guò)了 to-space 的容量,剩余的對(duì)象將被復(fù)制到老年代。可以選擇并行收集年輕代。
使用標(biāo)記-掃描-緊湊收集來(lái)收集終身代。有一個(gè)選項(xiàng)可以同時(shí)收集終身代。
-XX:MaxNewSize 的相關(guān)性是什么?-XX:NewSize 和 -XX:MaxNewSize 之間的差異會(huì)在哪里增長(zhǎng),Eden 或 Survivor Spaces?
年輕代由一個(gè)策略設(shè)置,該策略從下到上由 NewSize 限制大小,從上到下由 MaxNewSize 限制大小。隨著年輕一代從 NewSize 增長(zhǎng)到 MaxNewSize,伊甸園和幸存者空間都在增長(zhǎng)。
是否所有 eden-space 對(duì)象都移入了幸存者空間,以便在一次次 gc 之后,eden-space 是空的?
是的。如果 eden 中的所有活動(dòng)對(duì)象都無(wú)法放入幸存者空間,則剩余的活動(dòng)對(duì)象將被提升到老年代。
當(dāng)使用 -XX: TargetSurvivorRatio =90 時(shí),這會(huì)留下百分之十的空間用于從伊甸園中移動(dòng)對(duì)象嗎?
不。這意味著選擇了一個(gè) 任期閾值,以便根據(jù)上次次要收集中清除的內(nèi)容的年齡,應(yīng)該使用近 90% 的幸存者大小。從幸存者空間或伊甸園中清除的實(shí)際數(shù)量可能或多或少。
TargetSurvivorRatio 通常不會(huì)產(chǎn)生很大的影響。
如果 eden-space 中的對(duì)象需要的空間多于 to-survivor 空間中可用的空間,eden-space 對(duì)象是否會(huì)優(yōu)先于 from-survivor 空間對(duì)象?幸存者太空物體的年齡如何影響晉升?
在這里,來(lái)自伊甸園的東西和來(lái)自幸存者空間的東西沒(méi)有區(qū)別。次要收集完成后,伊甸園和來(lái)自幸存者的空間都是空的。如果 to-survivor 空間被填滿,任何剩余的對(duì)象都將直接提升到老年代,無(wú)論它們的年齡或來(lái)源如何。
在 NewSize 和 NewRatio 之間哪個(gè)選項(xiàng)優(yōu)先?
在 jdk 1.4.1 及更高版本中,兩者都沒(méi)有嚴(yán)格的優(yōu)先級(jí)。使用 NewSize 的最大值和使用 NewRatio 計(jì)算的大小。公式是
min (MaxNewSize, max (NewSize, heap/(NewRatio+1)))
2.永久代的規(guī)模應(yīng)該如何確定?
永久代用于保存 VM 本身的反射,例如類對(duì)象和方法對(duì)象。這些反射對(duì)象被直接分配到永久代,并且它的大小獨(dú)立于其他代。通常,可以忽略這一代的大小,因?yàn)槟J(rèn)大小已經(jīng)足夠了。但是,加載許多類的程序可能需要更大的永久代。
3.如何判斷永久代是否已滿?
從 1.4.2 開(kāi)始 -XX:+PrintGCDetails 將打印有關(guān)在每次垃圾回收時(shí)收集的堆的所有部分的信息。完整的收藏
[Full GC [Tenured: 30437K->33739K(280576K), 0.7050569 secs] 106231K->33739K(362112K), [Perm : 2919K->2919K(16384K)], 0.7052334 secs]
這個(gè)例子表明,永久代收集的很少(從收集前使用的 2919K 變?yōu)槭占笫褂玫?2919K),永久代的當(dāng)前大小為 16384K。
4.如何增加永久代的大???
使用命令行選項(xiàng) -XX:MaxPermSize=<desired size>
5.我如何知道正在加載或卸載哪些類?
使用命令行選項(xiàng) -XX:+ TraceClassloading和 -XX:+ TraceClassUnloading
6.年輕一代的最佳尺寸是多少?
年輕代的大小應(yīng)該足夠大,以便短期對(duì)象有機(jī)會(huì)在下一次年輕代收集之前死亡。這是一個(gè)權(quán)衡,因?yàn)楦蟮哪贻p代將允許對(duì)象有更多時(shí)間死亡,但也可能需要更長(zhǎng)的時(shí)間來(lái)收集。試驗(yàn)?zāi)贻p代的大小以優(yōu)化年輕代收集時(shí)間或 應(yīng)用程序吞吐量。
7.如果我的應(yīng)用程序有中長(zhǎng)壽命的對(duì)象,我該怎么辦?
在年輕代集合中存活的對(duì)象具有復(fù)制成本(年輕代集合的算法的一部分是復(fù)制任何存活的對(duì)象)。中期或長(zhǎng)期對(duì)象可能會(huì)被復(fù)制多次。使用 -XX 選項(xiàng)MaxTenuringThreshold 來(lái)確定復(fù)制成本。使用 -XX:MaxTenuringThreshold=0 將在年輕代集合中幸存的對(duì)象立即移動(dòng)到終身代。如果這提高了應(yīng)用程序的性能,那么長(zhǎng)期對(duì)象的復(fù)制就很重要。請(qǐng)注意,吞吐量收集器不使用 MaxTenuringThreshold 參數(shù)。
8.垃圾收集何時(shí)開(kāi)始?
在默認(rèn)垃圾收集器中,當(dāng)代已滿時(shí)(即,無(wú)法從該代進(jìn)行進(jìn)一步分配時(shí))會(huì)收集該代。吞吐量收集器也是如此。并發(fā)低暫停收集器在老年代的占用率達(dá)到指定值(默認(rèn)為 68%)時(shí)開(kāi)始收集。增量低暫停收集器在每次年輕代收集期間收集一部分老年代。集合也可以由應(yīng)用程序顯式啟動(dòng)。
9.System.gc() 做什么類型的集合?
執(zhí)行垃圾收集的顯式請(qǐng)求會(huì)執(zhí)行完整收集(年輕代和老生代)。完整的收集總是在應(yīng)用程序在收集期間暫停的情況下完成。
10.什么是并發(fā)標(biāo)記掃描 (CMS) 收集器?
Concurrent Mark Sweep (CMS) 收集器(也稱為并發(fā)低暫停收集器)收集tenured generation。它試圖通過(guò)與應(yīng)用程序線程同時(shí)進(jìn)行大部分垃圾收集工作來(lái) 最小化由于垃圾收集而導(dǎo)致的暫停。
11.為什么碎片是并發(fā)低暫停收集器的 潛在問(wèn)題?
通常并發(fā)低暫停收集器不會(huì)復(fù)制或壓縮活動(dòng)對(duì)象。垃圾收集是在不移動(dòng)活動(dòng)對(duì)象的情況下完成的。如果碎片成為問(wèn)題,請(qǐng)分配更大的堆。在 1.4.2 中,如果老年代的碎片成為一個(gè)問(wèn)題,老年代的壓縮將被完成,盡管不是同時(shí)進(jìn)行。在 1.4.1 中,如果啟用了UseCMSCompactAtFullCollection選項(xiàng),則會(huì)發(fā)生壓縮 。
-XX:+UseCMSCompactAtFullCollection
12.并發(fā)低暫停收集器的階段是什么?
收集涉及六個(gè)階段:
階段 1(初始檢查點(diǎn))涉及停止所有 Java 線程,標(biāo)記所有可從根直接訪問(wèn)的對(duì)象,并重新啟動(dòng) Java 線程。
階段 2(并發(fā)標(biāo)記)從標(biāo)記的對(duì)象開(kāi)始掃描,并傳遞標(biāo)記從根可到達(dá)的所有對(duì)象。mutator在下面 的并發(fā)階段 2、3 和 5 期間執(zhí)行,并且在這些階段期間在 CMS 生成中分配的任何對(duì)象(包括提升的對(duì)象)都會(huì)立即標(biāo)記為活動(dòng)的。
階段 3:在并發(fā)標(biāo)記階段,mutator 可能正在修改對(duì)象。自并發(fā)標(biāo)記階段開(kāi)始以來(lái)已修改的任何對(duì)象(并且在該階段隨后未掃描)都必須重新掃描。 階段 3(并發(fā)預(yù)清理)掃描已同時(shí)修改的對(duì)象。由于持續(xù)的mutator 活動(dòng),可能會(huì)多次掃描修改過(guò)的卡片。
第 4 階段(最終檢查點(diǎn))是一個(gè)停止世界的階段。隨著突變體的停止,最終的標(biāo)記是通過(guò)掃描從根可以到達(dá)的對(duì)象并掃描任何修改過(guò)的對(duì)象來(lái)完成的。請(qǐng)注意,在此階段之后,可能會(huì)有已標(biāo)記但不再存在的對(duì)象。此類對(duì)象將在當(dāng)前集合中存活,但將在下一個(gè)集合中收集。
階段 5(并發(fā)掃描)收集死對(duì)象。死對(duì)象的集合將對(duì)象的空間添加到空閑列表以供以后分配。此時(shí)可能會(huì)發(fā)生死對(duì)象的合并。請(qǐng)注意,活動(dòng)對(duì)象不會(huì)移動(dòng)。
階段 6(重置)清除數(shù)據(jù)結(jié)構(gòu),為下一次收集做準(zhǔn)備。
13.VM 是否分配大型 int 數(shù)組供自己使用?
JVM 確實(shí)分配大 int[] 的一個(gè)地方是當(dāng)它填滿 內(nèi)存的各個(gè)碎片部分以使垃圾收集器看起來(lái)完整時(shí)。例如,在 GC 之前每個(gè)線程本地分配緩沖區(qū)的未使用部分,或者在運(yùn)行 JVMPI 對(duì)象分配事件時(shí)的所有年輕代。
14.我可以看到有多少線程分配緩沖區(qū)未使用嗎?
有一個(gè)標(biāo)志, -XX:+ PrintTLAB,它將跟蹤 TLAB 上的所有操作。 特別是,它打印像
重置 TLAB:線程:0x0002d7d0 大?。?KB 未使用:76B 總碎片 0.004499
每次 TLAB 填充一個(gè) int[]。在這種情況下,未使用的尾隨 76B 將未被使用。
這是一個(gè) TLAB 已填滿并將分配一個(gè)新 TLAB 的示例。這里的垃圾量比較少。在為垃圾收集做準(zhǔn)備時(shí),可能會(huì)產(chǎn)生更多的浪費(fèi)。對(duì)于在垃圾收集之前顯示的 TLAB 輸出,例如
重置 TLAB:線程:0x0002d840 大?。?KB 未使用:7276B 總碎片 0.004580
[全 GC 10424K->591K(15688K),0.1222677 秒]
我們正在填充 8192 字節(jié) TLAB 的 7276 字節(jié)。(“總碎片”是由TLAB 引起的碎片的累積計(jì)算。)默認(rèn)情況下,在 SPARC 服務(wù)器上調(diào)整 TLAB 的大小,或者如果您使用 -XX:+ ResizeTLAB 標(biāo)志,因此如果您正在運(yùn)行,您很可能會(huì)得到大的TLAB那個(gè)JVM。請(qǐng)注意,我們不會(huì)在集合之前“浪費(fèi)”填充器的空間,因?yàn)榧蠈⒒謴?fù)填充器對(duì)象占用的空間。
15.NewRatio 的默認(rèn)值會(huì)隨著編譯器的變化而變化嗎?
在 SPARC 上,-XX:NewRatio 默認(rèn)為 -client 為 8,-server 為 2,因此年輕代與老年代的比率將為 1::8,而年輕代將是堆的 1/9 -客戶端和 1::2 或 1/3 的堆與 -server。
16.什么是并行垃圾收集器 (-XX:+UseParallelGC)?
新的并行垃圾收集器類似于默認(rèn)垃圾收集器中的年輕代收集器,但使用多個(gè)線程進(jìn)行收集。默認(rèn)情況下,在具有 N個(gè) CPU的主機(jī)上,并行垃圾收集器在收集中使用 N 個(gè)垃圾收集器線程。垃圾收集器線程的數(shù)量可以通過(guò)命令行選項(xiàng)來(lái)控制(見(jiàn)下文)。在具有單個(gè) CPU 的主機(jī)上,即使已請(qǐng)求并行垃圾收集器,也會(huì)使用默認(rèn)垃圾收集器。在具有 2 個(gè)cpu 的主機(jī)上,并行垃圾收集器的性能通常與默認(rèn)垃圾收集器一樣好,并且在具有超過(guò) 2 個(gè) cpu 的主機(jī)上可以預(yù)期減少年輕代垃圾收集器的暫停時(shí)間。
這個(gè)新的并行垃圾收集器可以通過(guò)使用命令行產(chǎn)品標(biāo)志 -XX:+UseParallelGC 來(lái)啟用??梢允褂?ParallelGCThreads 命令行選項(xiàng) (-XX:ParallelGCThreads=<desired number>) 控制垃圾收集器線程的數(shù)量。此收集器不能與并發(fā)低暫停收集器一起使用。
17.什么是并行年輕代收集器(-XX:+UseParNewGC)?
并行年輕代收集器在意圖上類似于并行垃圾收集器(-XX:+UseParallelGC),但在實(shí)現(xiàn)上有所不同。因此,以上對(duì)并行垃圾收集器 (-XX:+UseParallelGC) 的大部分描述同樣適用于并行年輕代收集器。與并行垃圾收集器 (-XX:+UseParallelGC) 不同,此并行年輕代收集器可以與收集終身代的并發(fā)低暫停收集器一起使用。
18.我應(yīng)該使用哪個(gè)并行收集器?
盡管意圖相似,但收集器在實(shí)現(xiàn)的某些細(xì)節(jié)上有所不同,這使得并行垃圾收集器更適合某些應(yīng)用程序,而并行年輕代收集器更適合其他應(yīng)用程序。兩者都應(yīng)該嘗試確定哪個(gè)可能更適合特定應(yīng)用程序。
此外,并行年輕代收集器 (-XX:+UseParNewGC) 與并發(fā)低暫停收集器集成,而并行垃圾收集器 (-XX:+UseParallelGC) 則沒(méi)有。即使不使用并發(fā)低暫停收集器,也會(huì)產(chǎn)生與此集成相關(guān)的一些成本。相反,并行垃圾收集器 (-XX:+UseParallelGC) 可以與自適應(yīng)大小 (-XX:+UseAdaptiveSizePolicy) 一起使用,而并行年輕代收集器 (-XX:+UseParNewGC) 則不能。
19.為什么并發(fā)低暫停 (CMS) 收集器的啟動(dòng)速度很慢?
使用 CMS (+XX:UseConcMarkSweepGC),您有時(shí)需要將最小和最大堆大小設(shè)置為相同的值(或至少設(shè)置一個(gè)較大的最小值),因?yàn)?CMS 有時(shí)會(huì)花時(shí)間提前增長(zhǎng)其堆。燙發(fā)一代也可能如此。使用選項(xiàng) -XX 嘗試更大的 perm 生成大?。篜ermSize =<initial size> -XX:MaxPermSize=<maximum size>。
20.什么年輕代收集器與并發(fā)低暫停收集器一起使用?
默認(rèn)情況下,低暫停收集器使用默認(rèn)的單線程年輕代復(fù)制收集器。如果您指定 +XX:UseParNewGC 將使用復(fù)制收集器的并行版本。
21.為什么低暫停收集器有時(shí)會(huì)比默認(rèn)收集器做更多的收集?
如果您沒(méi)有看到使用默認(rèn)收集器的主要收集,但看到使用并發(fā)低暫停收集器的許多主要收集,您可能會(huì)看到某種類型的碎片問(wèn)題。嘗試使用更大的堆和并發(fā)低暫停收集器。
22.垃圾收集文檔是否還有其他外部資源?
http://developer.java.sun.com/developer/technicalArticles/Programming/turbo/
23.對(duì)于并發(fā)低暫停收集器,NewRatio 的最小值是多少?
建議最小值 為4。
24.對(duì)象會(huì)直接分配到老年代嗎?
在 1.4.1 中有兩種情況,分配可能直接發(fā)生在老年代。
如果年輕代分配失敗,并且對(duì)象是一個(gè)不包含任何對(duì)象引用的大數(shù)組,則可以直接將其分配到年老代。在某些特定情況下,此策略旨在通過(guò)從老年代分配來(lái)避免收集年輕代。
有一個(gè)標(biāo)志(在 1.4.2 和更高版本中可用)l-XX: PretenureSizeThreshold =<byte size> 可以設(shè)置來(lái)限制年輕代中分配的大小。任何大于此的分配都不會(huì)在年輕代中嘗試,因此將被分配到老年代之外。
1) 的閾值大小為 64k 字。PretenureSizeThreshold 的默認(rèn)大小為 0,表示可以在年輕代中分配任何大小。
在 1.4.2 案例 1) 中,增量收集器 (-Xincgc) 的 64k 字閾值仍然有效。對(duì)于默認(rèn)收集器和并發(fā)收集器(-XX:+UseConcMarkSweepGC),閾值已更改,因此僅當(dāng)分配的大小大于整個(gè)年輕代(可用空間時(shí)它是空的)。據(jù)觀察,在某些情況下,默認(rèn)收集器和并發(fā)收集器的 1.4.1 策略僅導(dǎo)致完全收集(沒(méi)有進(jìn)行年輕代收集)。我們認(rèn)為這足以提高門檻。
25.我應(yīng)該增加客戶端虛擬機(jī)中永久代的大小嗎?
這將永遠(yuǎn)是一個(gè)判斷電話。一般來(lái)說(shuō),增加一代的大小(這不僅適用于永久代)可以減少各種問(wèn)題的發(fā)生率,但是,這可能會(huì)導(dǎo)致其他進(jìn)程過(guò)度分頁(yè)和/或垃圾收集或拋出-內(nèi)存異常。
有兩種故障模式需要考慮。
提高 MaxPermSize 時(shí),以前行為良好的程序可能會(huì)因無(wú)休止的分頁(yè)而死掉,這些程序用于垃圾收集以恢復(fù)永久代空間。對(duì)于永久代,這通常只發(fā)生在臨時(shí)字符串的大量實(shí)習(xí)中。
另一種故障模式是必須為永久代保留地址空間,這將減少堆其余部分的可用空間(最大值 -Xmx 可能會(huì)太大)。這將導(dǎo)致配置為使用所有可用空間的程序在初始化時(shí)失敗。
最近的 VM中的永久代默認(rèn)值。
發(fā)布
v1.3.1_06
v1.4.1_01
v1.4.2
客戶
永久大小
1M
4M
4M
服務(wù)器
永久大小
1M
4M
16M
客戶
最大燙發(fā)尺寸
32M
64M
64M
服務(wù)器
最大燙發(fā)尺寸
64M
64M
64M
我應(yīng)該匯集對(duì)象來(lái)幫助 GC 嗎?我應(yīng)該定期調(diào)用 System.gc() 嗎?
這些問(wèn)題的答案是否定的!
池化對(duì)象將導(dǎo)致它們的壽命超過(guò)必要的時(shí)間。我們強(qiáng)烈建議不要使用對(duì)象池。
不要調(diào)用 System.gc()。系統(tǒng)將確定何時(shí)適合進(jìn)行垃圾收集,并且通常具有更好地啟動(dòng)垃圾收集所需的信息。如果您在垃圾收集方面遇到問(wèn)題(暫停時(shí)間或頻率),請(qǐng)考慮調(diào)整代的大小。
什么決定了何時(shí)刷新軟引用的對(duì)象?
從 J2SE 1.3.1 中的 Java HotSpot VM 實(shí)現(xiàn)開(kāi)始,軟可訪問(wèn)對(duì)象將在最后一次被引用后保持活動(dòng)一段時(shí)間。默認(rèn)值是堆中每兆字節(jié)的生命周期一秒。該值可以使用 -XX:SoftRefLRUPolicyMSPerMB 標(biāo)志進(jìn)行調(diào)整,該標(biāo)志接受表示每 MB 可用內(nèi)存毫秒數(shù)的整數(shù)值。例如,要將值從 1 秒更改為 2.5 秒,請(qǐng)使用以下標(biāo)志:
-XX:SoftRefLRUPolicyMSPerMB =2500
Java HotSpot Server VM 使用最大可能的堆大?。ㄓ?-Xmx 選項(xiàng)設(shè)置)來(lái)計(jì)算剩余的可用空間。
Java HotSpot Client VM 使用當(dāng)前堆大小來(lái)計(jì)算可用空間。
這意味著服務(wù)器 VM 的總體趨勢(shì)是增加堆而不是刷新軟引用,因此 -Xmx 對(duì)軟引用何時(shí)被垃圾收集具有顯著影響。
另一方面,客戶端虛擬機(jī)將更傾向于刷新軟引用而不是增加堆。
上述行為適用于 Java HotSpot VM 的當(dāng)前(J2SE 1.3.1 和 J2SE 1.4.x)版本。 請(qǐng)注意,不保證 -XX:SoftRefLRUPolicyMSPerMB 標(biāo)志存在于任何給定版本中。
在 1.3.1 版之前,Java HotSpot VM 在找到軟引用時(shí)會(huì)清除它們。
當(dāng)我打開(kāi) -verbose:gc 時(shí),我得到了很多完整的垃圾回收( GC ) 。GC 定期進(jìn)行。我的應(yīng)用程序從不調(diào)用 System.gc。我已經(jīng)調(diào)整了堆,它沒(méi)有任何區(qū)別,這是怎么回事?
如果您使用的是 RMI(遠(yuǎn)程方法調(diào)用),那么您可能會(huì)遇到分布式垃圾回收 (GC)。此外,一些應(yīng)用程序正在添加顯式 GC 的想法,認(rèn)為這將使他們的應(yīng)用程序更快。幸運(yùn)的是,您可以使用 1.3 和 1.4 版本中提供的選項(xiàng)禁用此功能。嘗試 -XX:+ DisableExplicitGC 和 -verbose:gc 看看這是否有幫助。
并發(fā)低暫停收集器似乎大部分時(shí)間都在進(jìn)行完整收集。如何加快并發(fā)收集?
并發(fā)收集通常無(wú)法加速,但可以更早地啟動(dòng)。
當(dāng)老年代中分配的空間百分比超過(guò)閾值時(shí),并發(fā)收集開(kāi)始運(yùn)行。此閾值是根據(jù)并發(fā)收集器的一般經(jīng)驗(yàn)計(jì)算得出的。如果正在發(fā)生完整收集,則可能需要更早地啟動(dòng)并發(fā)收集。命令行標(biāo)志 CMSInitiatingOccupancyFraction 可用于設(shè)置開(kāi)始收集的級(jí)別。其默認(rèn)值約為 68%。調(diào)整值的命令行是
-XX:CMSInitiatingOccupancyFraction=<百分比>
并發(fā)收集器還會(huì)統(tǒng)計(jì)應(yīng)用程序進(jìn)入老年代的提升率,并根據(jù)提升率和老年代的可用空間來(lái)預(yù)測(cè)何時(shí)開(kāi)始并發(fā)收集。盡管 CMSInitiatingOccupancyFraction 的使用必須保守以避免在應(yīng)用程序的生命周期內(nèi)完全收集,但基于預(yù)期提升的并發(fā)收集的啟動(dòng)適應(yīng)應(yīng)用程序不斷變化的需求。用于計(jì)算提升率的統(tǒng)計(jì)信息基于最近的并發(fā)收集。在至少一個(gè)并發(fā)收集完成之前不會(huì)計(jì)算提升率,因此至少必須啟動(dòng)第一個(gè)并發(fā)收集,因?yàn)檎加寐室堰_(dá)到 CMSInitiatingOccupancyFraction 。將 CMSInitiatingOccupancyFraction 設(shè)置為 100 不會(huì)導(dǎo)致僅使用預(yù)期提升來(lái)啟動(dòng)并發(fā)收集,而是只會(huì)導(dǎo)致非并發(fā)收集發(fā)生,因?yàn)椴l(fā)收集直到為時(shí)已晚才會(huì)啟動(dòng)。消除使用預(yù)期提升來(lái)啟動(dòng)并發(fā)收集集UseCMSInitiatingOccupancyOnly 為真。
-XX:+UseCMSInitiatingOccupancyOnly
有時(shí),當(dāng)一個(gè)完整的收集開(kāi)始時(shí),并發(fā)低暫停收集器即將完成并發(fā)收集的最后一部分。完整的集合看起來(lái)就像它再次完成了整個(gè)集合。這會(huì)發(fā)生嗎?
默認(rèn)情況下,完整集合使用與并發(fā)集合不同的集合算法(壓縮)。因此,正在進(jìn)行的并發(fā)收集所做的所有工作都會(huì)丟失。可以對(duì)此進(jìn)行調(diào)整,以便完整收集將完成并發(fā)收集,盡管不是同時(shí)進(jìn)行。一個(gè)完整的集合通常會(huì)進(jìn)行壓縮,因?yàn)闊o(wú)法同時(shí)完成它的集合通常是碎片問(wèn)題的標(biāo)志。在許多情況下,需要進(jìn)行壓縮,但可以通過(guò)將 CMSFullGCsBeforeCompaction的值設(shè)置為 1 來(lái)延遲 1 次完整收集 。
-XX:CMSFullGCsBeforeCompaction=1
當(dāng)一個(gè)完整的收集開(kāi)始時(shí)使用這個(gè)值,它將完成正在進(jìn)行的并發(fā)收集。如果在正常并發(fā)收集完成之前發(fā)生另一個(gè)完整收集,則將完成壓縮。
使用并發(fā)低暫停收集器,我如何知道還剩下多少浮動(dòng)垃圾?
因?yàn)閼?yīng)用程序線程和 GC 線程同時(shí)運(yùn)行,所以在收集開(kāi)始時(shí)處于活動(dòng)狀態(tài)且 GC 線程已標(biāo)記為活動(dòng)的對(duì)象可能會(huì)在收集結(jié)束時(shí)死亡。這樣的對(duì)象被稱為浮動(dòng)垃圾。如果在并發(fā)收集之后立即發(fā)生完全壓縮收集,則可以推斷出浮動(dòng)垃圾的數(shù)量。堆大小的任何減少都是由于浮動(dòng)垃圾。
并行收集器似乎使用與機(jī)器上的處理器一樣多的垃圾收集器 (GC) 線程。如何請(qǐng)求更多或更少的 GC 線程?
GC線程數(shù)由選項(xiàng)控制
-XX:ParallelGCThreads=<number_of_GC_threads>
為什么并發(fā)低暫停收集器會(huì)出現(xiàn)碎片?
并發(fā)低暫停收集器通常不會(huì)在垃圾收集期間移動(dòng)對(duì)象。當(dāng)活動(dòng)對(duì)象散布在收集結(jié)果留下的可用空間時(shí),就會(huì)發(fā)生碎片。例外情況是發(fā)生非并發(fā)的完整收集時(shí)。在后一種情況下,應(yīng)用程序在收集期間停止,活動(dòng)對(duì)象被壓縮到一代的一端,所有空閑空間都駐留在一個(gè)連續(xù)的塊中。
吞吐量收集器應(yīng)該使用哪些選項(xiàng)?
使用的正確選項(xiàng)取決于您的應(yīng)用程序。以下是一些典型用途,但這些都不是最適合您的應(yīng)用程序的。
服務(wù)器應(yīng)用程序單獨(dú)運(yùn)行在具有 4GB 物理內(nèi)存的大型多處理器服務(wù)器上。
#java -server -XX:+AggressiveHeap
兩個(gè)應(yīng)用程序?qū)嵗诰哂?4GB 物理內(nèi)存的大型多處理器服務(wù)器上運(yùn)行。每個(gè) java 應(yīng)用程序?qū)嵗纪ㄟ^(guò)最大和最小堆大小的顯式規(guī)范分配總系統(tǒng)內(nèi)存的一部分。
#java -server -XX:+AggressiveHeap -Xms1024m -Xmx1024m
不使用 AggressiveHeap 標(biāo)志的示例
#java -server -XX:+UseParallelGC -XX:ParallelGCThreads=4 -Xms1024m -Xmx1024m
并發(fā)低暫停收集器應(yīng)該使用哪些選項(xiàng)?
使用的正確選項(xiàng)取決于您的應(yīng)用程序。以下是一些典型用途,但這些都不是最適合您的應(yīng)用程序的。
在具有 1 GB 物理內(nèi)存的處理器系統(tǒng)上運(yùn)行的服務(wù)器應(yīng)用程序。
#java -Xmx512m -Xms512m -XX:MaxNewSize=24m -XX:NewSize=24m -XX:+UseConcMarkSweepGC
在具有 1GB 物理內(nèi)存的多處理器系統(tǒng)上運(yùn)行的服務(wù)器應(yīng)用程序 - 使用并行次要收集選項(xiàng)。
#java -Xmx512m -Xms512m -XX:MaxNewSize=24m -XX:NewSize=24m -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseConcMarkSweepGC
并發(fā)低暫停收集器的默認(rèn)設(shè)置是什么?
并發(fā)低暫停收集器的默認(rèn)堆大小與默認(rèn)收集器相同。其他參數(shù)的設(shè)置如下所述。這些設(shè)置已被證明適用于具有大部分壽命很短的數(shù)據(jù)以及一些壽命很長(zhǎng)的數(shù)據(jù)的應(yīng)用程序。一些選項(xiàng)需要用尖括號(hào) (<>) 括起來(lái)的計(jì)算,其中兩個(gè)取決于機(jī)器上的 CPU 數(shù)量 (#cpus。)
# 啟用并發(fā)低暫停收集器
-XX:+UseConcMarkSweepGC
# 使用并行線程
-XX:+UseParNewGC
-XX:ParallelGCThreads=<#cpus < 8 ? #cpus : 3 + ((5 * #cpus) / 8) >
-XX:+CMSParallelRemarkEnabled
# 為短暫的停頓調(diào)整年輕代的大小
-XX:NewSize=4m
-XX:MaxNewSize=< 4m * ParallelGCThreads >
# 提升所有活躍的年輕代對(duì)象
-XX: MaxTenuringThreshold = 0
-XX:幸存者比率=1024
還建議使用比默認(rèn)收集器使用的堆大小大 20-30% 的堆大小。
增量低暫停收集器應(yīng)該使用哪些選項(xiàng)?
使用的正確選項(xiàng)取決于您的應(yīng)用程序。以下是一些典型用途,但這些都不是最適合您的應(yīng)用程序的。
具有 1GB 物理內(nèi)存的服務(wù)器應(yīng)用程序。
#java -server -Xincgc -XX:NewSize=64m -XX:MaxNewSize=64m -Xms512m -Xmx512m
如果發(fā)生完全收集,則上面的應(yīng)用程序表明沒(méi)有足夠快地增量收集終身代。
#java -server -Xincgc -XX:NewSize=24m -XX:MaxNewSize=24m -Xms512m -Xmx512m
草稿版本:2003 年 2 月 6 日
版權(quán)所有 ? 2003 Sun Microsystems, Inc.。保留所有權(quán)利。