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

Java?垃圾回收超詳細(xì)講解記憶集和卡表

 更新時(shí)間:2022年04月07日 18:47:11   作者:田埂、  
卡表就是記憶集的一種具體實(shí)現(xiàn),它定義了記憶集的記錄精度、與堆內(nèi)存的映射關(guān)系等。?關(guān)于卡表與記憶集的關(guān)系,不妨按照J(rèn)ava語言中HashMap與Map的關(guān)系來類比理解。記憶集是一種用于記錄從非收集區(qū)域指向收集區(qū)域的指針集合的抽象數(shù)據(jù)結(jié)構(gòu)

跨代引用

在說記憶集和卡表之前,先給大家介紹一下跨代引用的問題。

假如要現(xiàn)在進(jìn)行一次只局限于新生代區(qū)域內(nèi)的收集(Minor GC),但新生代的實(shí)例對象1在老年代中被引用,為了找出該區(qū)域(新生代)中所有的存活對象,不得不在固定的GC Roots之外,再額外遍歷整個(gè)老年代中所有對象來確保可達(dá)性分析結(jié)果的正確性,反過來也是一樣。遍歷整個(gè)老年代所有對象的方案雖然理論上可行,但無疑會為內(nèi)存回收帶來很大的性能負(fù)擔(dān)。

事實(shí)上并不只是新生代、老年代之間才有跨代引用的問題,所有涉及部分區(qū)域收集(Partial GC)行為的垃圾收集器,典型的如G1、ZGC和Shenandoah收集器,都會面臨相同的問題。

解決跨代引用

首先,跨代引用相對于同代引用來說僅占極少數(shù)。原因是跨代引用的對象應(yīng)該傾向于同時(shí)生存或者同時(shí)死亡的(舉個(gè):如果某個(gè)新生代對象存在跨代引用,由于老年代對象難以消亡,該引用會使得新生代對象在收集時(shí)同樣得以存活,進(jìn)而在年齡增長之后晉升到老年代中,這時(shí)跨代引用也隨即被消除了)。

依據(jù)上面說所,就不應(yīng)再為了少量的跨代引用去掃描整個(gè)老年代,也不必浪費(fèi)空間專門記錄每一個(gè)對象是否存在及存在哪些跨代引用,只需在新生代上建立一個(gè)全局的數(shù)據(jù)結(jié)構(gòu)(該結(jié)構(gòu)被稱為“記憶集”,Remembered Set),這個(gè)結(jié)構(gòu)把老年代劃分成若干小塊,標(biāo)識出老年代的哪一塊內(nèi)存會存在跨代引用。此后當(dāng)發(fā)生Minor GC時(shí),只有包含了跨代引用的小塊內(nèi)存里的對象才會被加入到GCRoots進(jìn)行掃描。雖然這種方法需要在對象改變引用關(guān)系(如將自己或者某個(gè)屬性賦值)時(shí)維護(hù)記錄數(shù)據(jù)的正確性,會增加一些運(yùn)行時(shí)的開銷,但比起收集時(shí)掃描整個(gè)老年代來說仍然是劃算的。

下面就來介紹一下這個(gè)全局的數(shù)據(jù)結(jié)構(gòu)記憶集。

記憶集

記憶集是一種用于記錄從非收集區(qū)域指向收集區(qū)域的指針集合的抽象數(shù)據(jù)結(jié)構(gòu)。如果我們不考慮效率和成本的話,最簡單的實(shí)現(xiàn)可以用非收集區(qū)域中所有含跨代引用的對象數(shù)組來實(shí)現(xiàn)這個(gè)數(shù)據(jù)結(jié)構(gòu),如下面代碼所示:

//以對象指針來實(shí)現(xiàn)記憶集的偽代碼
Class RememberedSet {
	Object[] set[OBJECT_INTERGENERATIONAL_REFERENCE_SIZE]; 
}

這種記錄全部含跨代引用對象的實(shí)現(xiàn)方案,無論是空間占用還是維護(hù)成本都相當(dāng)高昂。而在垃圾收集的場景中,收集器只需要通過記憶集判斷出某一塊非收集區(qū)域是否存在有指向了收集區(qū)域的指針就可以了,并不需要了解這些跨代指針的全部細(xì)節(jié)。那設(shè)計(jì)者在實(shí)現(xiàn)記憶集的時(shí)候,便可以選擇更為粗獷的記錄粒度來節(jié)省記憶集的存儲和維護(hù)成本。下面列舉了一些可供選擇(當(dāng)然也可以選擇這個(gè)范圍以外的)的記錄精度:

  • 字長精度:每個(gè)記錄精確到一個(gè)機(jī)器字長(就是處理器的尋址位數(shù),如常見的32位或64位,這個(gè) 精度決定了機(jī)器訪問物理內(nèi)存地址的指針長度),該字包含跨代指針。
  • 對象精度:每個(gè)記錄精確到一個(gè)對象,該對象里有字段含有跨代指針。
  • 卡精度:每個(gè)記錄精確到一塊內(nèi)存區(qū)域,該區(qū)域內(nèi)有對象含有跨代指針。

上面的,第三種“卡精度”所指的是用一種稱為“卡表”(Card Table)的方式去實(shí)現(xiàn)記憶集,這也是目前最常用的記憶集的實(shí)現(xiàn)形式。

卡表和記憶集又有什么關(guān)系呢?

前面介紹記憶集的時(shí)候提到 記憶集其實(shí)是一種"抽象”的數(shù)據(jù)結(jié)構(gòu),抽象的意思是只定義了記憶集的行為意圖,并沒有定義其行為的具體實(shí)現(xiàn)??ū砭褪怯洃浖囊环N具體實(shí)現(xiàn),它定義了記憶集的記錄精度、與堆內(nèi)存的映射關(guān)系等。關(guān)于記憶集與卡表的關(guān)系,可以按照J(rèn)ava中Map與HashMap的關(guān)系來類比理解(即接口和實(shí)現(xiàn)類來的關(guān)系)。

下面來詳細(xì)說一下記憶集的具體實(shí)現(xiàn)卡表

卡表

卡表是使用一個(gè)字節(jié)數(shù)組CARD_TABLE[] 實(shí)現(xiàn),每個(gè)元素對應(yīng)其標(biāo)識的內(nèi)存區(qū)域一塊特定大小的內(nèi)存塊,每個(gè)內(nèi)存塊稱為卡頁,hotspot使用的卡頁是2^9大小 即512字節(jié)。如下圖所示

這樣我們就可以把某個(gè)區(qū)域按照卡頁進(jìn)行劃分,假如我們現(xiàn)在要對新生代區(qū)域進(jìn)行垃圾回收,那么就可以把老年代區(qū)域看成是一個(gè)卡頁一個(gè)卡頁劃分好的,如下圖所示。

如圖所示,因?yàn)閏ardpage1中存在指向新生代的跨代引用,所以對應(yīng)卡表的第一個(gè)位置為1,表明該page區(qū)域存在跨代應(yīng)用的對象。

  • 卡表角度:因?yàn)閜age1中存在跨代飲用的對象,所以卡表對應(yīng)的第一個(gè)位置記為1,表明page1這個(gè)元素變臟。
  • 內(nèi)存回收角度:因?yàn)榭ū淼牡谝粋€(gè)位置為1,表明該page區(qū)域存在跨代應(yīng)用的對象,垃圾回收的時(shí)候需要掃描該區(qū)域。

一個(gè)卡頁的內(nèi)存中通常包含不止一個(gè)對象,只要卡頁內(nèi)有一個(gè)(或更多)對象的字段存在著跨代指針,那就將對應(yīng)卡表的數(shù)組元素的值標(biāo)識為1,稱為這個(gè)元素變臟(Dirty),沒有則標(biāo)識為0。在垃圾收集發(fā)生時(shí),只要篩選出卡表中變臟的元素,就能輕易得出哪些卡頁內(nèi)存塊中包含跨代指針,把它們加入GC Roots中一并掃描。這樣就不需要掃描整個(gè)老年代大大減少GC Roots的掃描范圍。 

到此這篇關(guān)于Java 萬字超詳細(xì)講解記憶集和卡表的文章就介紹到這了,更多相關(guān)Java 記憶集和卡表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文帶你快速了解java中的static關(guān)鍵詞

    一文帶你快速了解java中的static關(guān)鍵詞

    這篇文章主要給大家介紹了關(guān)于java中static關(guān)鍵詞的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 聊聊ResourceBundle和properties讀取配置文件的區(qū)別

    聊聊ResourceBundle和properties讀取配置文件的區(qū)別

    這篇文章主要介紹了ResourceBundle和properties讀取配置文件的區(qū)別,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • IDEA編寫JavaWeb出現(xiàn)亂碼問題解決方案

    IDEA編寫JavaWeb出現(xiàn)亂碼問題解決方案

    這篇文章主要介紹了IDEA編寫JavaWeb出現(xiàn)亂碼問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SWT(JFace) Menu、Bar...體驗(yàn)代碼

    SWT(JFace) Menu、Bar...體驗(yàn)代碼

    SWT(JFace)體驗(yàn)之Menu、Bar實(shí)現(xiàn)代碼。
    2009-06-06
  • 基于JAVA代碼 獲取手機(jī)基本信息(本機(jī)號碼,SDK版本,系統(tǒng)版本,手機(jī)型號)

    基于JAVA代碼 獲取手機(jī)基本信息(本機(jī)號碼,SDK版本,系統(tǒng)版本,手機(jī)型號)

    本文給大家介紹基于java代碼獲取手機(jī)基本信息,包括獲取電話管理對象、獲取手機(jī)號碼、獲取手機(jī)型號、獲取SDK版本、獲取系統(tǒng)版本等相關(guān)信息,對本文感興趣的朋友一起學(xué)習(xí)吧
    2015-12-12
  • Spring源碼解析之Configuration

    Spring源碼解析之Configuration

    今天帶大家來學(xué)習(xí)Java Spring相關(guān)知識,文中對Configuration源碼介紹的非常詳細(xì),有非常多的圖文解說及代碼示例,對正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • SpringBoot全局配置long轉(zhuǎn)String丟失精度問題解決方案

    SpringBoot全局配置long轉(zhuǎn)String丟失精度問題解決方案

    這篇文章主要介紹了SpringBoot全局配置long轉(zhuǎn)String丟失精度問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • java生成XML的方法【附demo源碼下載】

    java生成XML的方法【附demo源碼下載】

    這篇文章主要介紹了java生成XML的方法,涉及java針對xml格式文件的簡單操作技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下
    2016-12-12
  • Java Collection集合遍歷運(yùn)行代碼實(shí)例

    Java Collection集合遍歷運(yùn)行代碼實(shí)例

    這篇文章主要介紹了Java Collection集合遍歷運(yùn)行代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Java編程中使用lambda表達(dá)式的奇技淫巧

    Java編程中使用lambda表達(dá)式的奇技淫巧

    這篇文章主要介紹了Java編程中使用lambda表達(dá)式的奇技淫巧,使用Lambda表達(dá)式可以替代只有一個(gè)函數(shù)的接口實(shí)現(xiàn),告別匿名內(nèi)部類,代碼看起來更簡潔易懂,是Java8開始推出的人們期待已久的功能,需要的朋友可以參考下
    2016-03-03

最新評論