欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JVM回收跨代垃圾的方式詳解

 更新時間:2024年02月27日 08:26:02   作者:半畝方塘立身  
在Java堆內(nèi)存中,年輕代和老年代之間存在的對象相互引用,假設(shè)現(xiàn)在要進(jìn)行一次新生代的YGC,但新生代中的對象可能被老年代所引用的,為了找到新生代中的存活對象,不得不遍歷整個老年代,這樣明顯效率很低下,那么如何快速識別并回收這種引用對象呢

1. 跨代引用概述

在Java堆內(nèi)存中,年輕代和老年代之間存在的對象相互引用,假設(shè)現(xiàn)在要進(jìn)行一次新生代的YGC,但新生代中的對象可能被老年代所引用的,為了找到新生代中的存活對象,不得不遍歷整個老年代。這樣明顯效率很低下,那么如何快速識別并回收這種引用對象呢?

這就不得不提到Card Table(卡表)和 Remember Set(記憶集,簡稱RSet)了。

2. 跨代引用的處理方式

2.1 卡表(Card Table)

卡表是一種用于跟蹤年輕代對象被老年代對象引用的數(shù)據(jù)結(jié)構(gòu)。它將堆內(nèi)存劃分為一系列固定大小的區(qū)域(卡片),每個卡片記錄了年輕代對象被老年代對象引用的情況。在老年代垃圾回收時,垃圾收集器會掃描卡表,以確定哪些年輕代對象是存活的,即被老年代對象引用。

在 JVM 中,一個 card 的大小(通常是)512字節(jié)。在多線程并行收集時,每個線程可以批量掃描多個 card,一批 card 被稱為一個 stride。默認(rèn)一個 stride 含有 256個 card,即每個線程要每次掃描 512 * 256 = 128 K 的內(nèi)存區(qū)域。stride數(shù)量太多就會導(dǎo)致線程在stride之間切換的開銷增加,進(jìn)而導(dǎo)致 GC Pause 增長, strides 太少恐怕也會導(dǎo)致單次掃描的時間增長,進(jìn)而影響整個 GC Pause 。

2.2 記憶集(Remembered Sets)

伴隨 G1 垃圾收集器的誕生,傳統(tǒng)的老年代和新生代都從物理上的連續(xù)空間,變成了一個個物理上不連續(xù)的空間 region。

JVM 針對這些Region 提供了一個數(shù)據(jù)結(jié)構(gòu),也就是 CSet(Collection Set),存儲任意年代的region。

物理上不連續(xù)的 region 造成了新生代和老年的引用破碎化,新生代引用老年代,所以產(chǎn)生了 old->youngyoung->old的跨代對象引用,這時候 JVM 只要掃描 CSet 中的 R Set 即可。

邏輯上說每個Region都有一個RSet,RSet記錄了其他Region中的對象引用本Region中對象的關(guān)系。

每個Region會在自身的Remembered Set中紀(jì)錄下來自其他Region的指向自身的Card位置。這個Remembered Set是一個Hash Table,Key是別的Region的起始地址,Value是一個集合,里面的元素是Card Table的Index。

RSet、Card和Region的關(guān)系

下圖表示了RSet、Card和Region的關(guān)系: 

圖中是相互引用的三個region。R1 和 R3 的被細(xì)分到了card table 級別。R2 被 R1 和 R3的某些區(qū)域引用,所以 R2 的 RSet 會記錄到 R1 和 R2 的區(qū)域索引,即產(chǎn)生某些循環(huán)引用的作用。

一個 Region 的 RSet 如果有值,至少可以證明這個區(qū)域是有引用的;一個區(qū)域如果無值,則可以認(rèn)為這個區(qū)域不可達(dá),可以不掃描這個區(qū)域(Card Table 可以減少 Minor GC 掃描 old 區(qū)來理解 young 區(qū)的時間,RSet 則可以減少掃描生成 CSet 選取候選 region 的時間)。

在做YGC的時候,只需要選定young generation region的RSet作為根集,這些RSet記錄了old->young的跨代引用,避免了掃描整個old generation。而mixed gc的時候,old generation中記錄了old->old的 RSet,young->old的引用由掃描全部young generation region(的 card table)得到,這樣也不用掃描全部old generation region。所以RSet的引入大大減少了GC的工作量。

2.3 處理器屏障(Processor Barriers)

處理器屏障是一種硬件支持的機制,用于跟蹤對象之間的引用關(guān)系。當(dāng)發(fā)生引用修改時,處理器屏障可以監(jiān)測到對內(nèi)存的訪問,并通知垃圾收集器。垃圾收集器可以根據(jù)這些信息來更新引用關(guān)系,確保跨代引用被正確處理。

3. 總結(jié)

卡表只解決 youngGC 掃老年代的問題,而 RSet 則解決了(G1 對)所有 Region 的掃描問題??ū硗ㄟ^對外引用提示我們應(yīng)該掃描什么區(qū)域,這樣我們可以避開不用掃描的區(qū)域;RSet通過對內(nèi)引用提示我們應(yīng)該掃描什么區(qū)域,這樣我們可以避開不用掃描的區(qū)域。

跨代引用的垃圾回收是Java虛擬機中一個復(fù)雜而重要的問題。通過合理設(shè)計和優(yōu)化記憶集、卡表等數(shù)據(jù)結(jié)構(gòu),并結(jié)合并發(fā)標(biāo)記-清除算法、處理器屏障等技術(shù),可以有效地處理跨代引用,保證垃圾回收的效率和穩(wěn)定性,從而提高Java應(yīng)用程序的性能和可靠性。

以上就是JVM回收跨代垃圾的方式詳解的詳細(xì)內(nèi)容,更多關(guān)于JVM回收跨代垃圾的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論