jvm垃圾收集算法和收集時(shí)機(jī)

哪些內(nèi)存需要回收

什么時(shí)候回收

如何回收

垃圾回收線程是守護(hù)線程,平常到達(dá)安全點(diǎn)和安全區(qū)域時(shí)會(huì)回收,當(dāng)堆內(nèi)存占用到達(dá)上限時(shí)Full GC

3.1引用計(jì)數(shù)算法和可達(dá)性分析算法

3.1.1引用計(jì)數(shù)算法

在對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)引用它時(shí)計(jì)數(shù)器就加一;當(dāng)引用失效時(shí)計(jì)數(shù)器就減一;任何時(shí)刻計(jì)數(shù)器為零的對(duì)象就是不可能再被使用的;

缺點(diǎn):如果兩個(gè)對(duì)象相互引用不會(huì)被回收

3.1.2可達(dá)性分析算法

一般虛擬機(jī)采用的是這種方法

基本思路:通過(guò)一系列被稱為“GC Roots”的根對(duì)象作為起始節(jié)點(diǎn)集,從這些節(jié)點(diǎn)開(kāi)始根據(jù)引用關(guān)系向下搜索,搜索過(guò)程走過(guò)的路徑稱為“引用鏈”,如果某個(gè)對(duì)象到GC Root之間沒(méi)有任何引用鏈,代表對(duì)象不可達(dá),則證明此對(duì)象不會(huì)再被使用

GC Root 有(可以根據(jù)具體的場(chǎng)景指定,下邊的相當(dāng)于是全局回收時(shí)用到的):

虛擬機(jī)棧 中引用的對(duì)象

方法區(qū) 中類(lèi)靜態(tài)屬性引用的對(duì)象,常量引用的對(duì)象

虛擬機(jī)內(nèi)部的引用? Class對(duì)象中的一些異常對(duì)象 空指針,堆溢出

同步鎖持有的對(duì)象 synchronized

當(dāng)分代回收時(shí),是局部回收,就可以指定要回收的代為GC Root

強(qiáng)引用、軟引用、弱引用、虛引用

為了再次細(xì)化垃圾回收的時(shí)機(jī),又將已經(jīng)被引用的對(duì)象細(xì)分為這四種狀態(tài)

強(qiáng)引用:一般理解的引用 Object object = new Object();

軟引用:還有些用但非必須的對(duì)象,GC之后內(nèi)存還是不夠,會(huì)在內(nèi)存溢出之前對(duì)這些對(duì)象進(jìn)行二次回收

弱引用:表示只能生存到下次垃圾回收

虛引用:虛引用不會(huì)影響回收時(shí)間,只是會(huì)在回收時(shí)收到一個(gè)系統(tǒng)通知

3.2方法區(qū)的回收

方法區(qū)的回收性價(jià)比比較低,是否回收可以通過(guò)配置設(shè)置

回收條件:

1.類(lèi)所有的實(shí)例已經(jīng)被回收,包括所有的派生類(lèi)

2.這個(gè)類(lèi)的類(lèi)加載器已經(jīng)被回收,這種場(chǎng)景存在于OSGI JSP的重新加載

3.類(lèi)的Class對(duì)象沒(méi)有任何地方被引用

3.3垃圾回收算法

準(zhǔn)備工作:分代,堆分為年輕代和老年代(G1是將堆分為若干Region)

針對(duì)不同的分代采用不同的回收類(lèi)型

Minor GC(年輕代)? Major GC(老年代) Full GC(堆+方法區(qū))

不同的區(qū)域也可以采用不同的算法:標(biāo)記-復(fù)制、標(biāo)記-清除、標(biāo)記-整理

3.3.1標(biāo)記清除算法

標(biāo)記要清除的對(duì)象或者標(biāo)記不需要清除的對(duì)象,然后進(jìn)行清除

缺點(diǎn):

1.如果需要回收的對(duì)象過(guò)程,需要進(jìn)行大量的標(biāo)記清除動(dòng)作,執(zhí)行效率會(huì)降低

2.容易產(chǎn)生內(nèi)存碎片,內(nèi)存利用率低

“分區(qū)空閑鏈表” 表明現(xiàn)在的可用空間

3.3.2標(biāo)記復(fù)制算法

基本思想“半?yún)^(qū)復(fù)制”,將內(nèi)存安裝大小分為兩個(gè)相同的區(qū)域,每次只使用其中的一塊,當(dāng)這塊用完時(shí),將活著的對(duì)象復(fù)制到另一塊,再將原來(lái)的一塊清空。

實(shí)際使用中不按1:1的比例劃分,好比是9:1的比例,復(fù)制時(shí)第二塊就有可能裝不下就需要有其他內(nèi)存做為擔(dān)保,一般用老年代做擔(dān)保。

老年代沒(méi)有擔(dān)??臻g,就不方便采用這種算法

HotSpot對(duì)年輕代采用的是這種算法,將年輕代分為Eden和兩個(gè)Survivor

3.3.3標(biāo)記整理

標(biāo)記對(duì)象,將存活的對(duì)象移動(dòng)至內(nèi)存前端

缺點(diǎn):對(duì)象移動(dòng)時(shí)需要用戶程序停止即“Stop The World”

可以將標(biāo)記清除和標(biāo)記整理配合使用,當(dāng)內(nèi)存碎片影響內(nèi)存分配時(shí)使用一次標(biāo)記整理

3.4OopMap、安全點(diǎn)、安全區(qū)域

一旦觸發(fā)了垃圾回收,如何確定垃圾回收線程的執(zhí)行時(shí)間

Hotspot為了確定垃圾回收的時(shí)間引入了安全點(diǎn)和安全區(qū)域的概念,安全點(diǎn)和安全區(qū)域代表內(nèi)存區(qū)域沒(méi)有發(fā)生變化,這個(gè)時(shí)候能夠允許回收線程和用戶線程可以同時(shí)進(jìn)行

3.4.1用OopMap埋點(diǎn)? 這個(gè)重新看一下,尋找對(duì)象的引用關(guān)系應(yīng)該是內(nèi)存的角度

Hotspot在類(lèi)加載完成時(shí)用OoMap的數(shù)據(jù)結(jié)構(gòu)記錄了對(duì)象的引用關(guān)系,在編譯完的字節(jié)碼文件中有這種記錄的體現(xiàn),當(dāng)進(jìn)行GC時(shí)不需要從GC Roots開(kāi)始進(jìn)行查找

OopMap在字節(jié)碼文件表明從某個(gè)位置到某個(gè)位置引用了某個(gè)對(duì)象

3.4.2安全點(diǎn)

OopMap記錄的位置即為安全點(diǎn)

用戶線程到達(dá)安全點(diǎn)之后會(huì)將自己掛起,等待GC線程執(zhí)行

安全點(diǎn):方法調(diào)用、循環(huán)跳轉(zhuǎn)、異常跳轉(zhuǎn)

3.4.3安全區(qū)域

某一段代碼片段之中,引用關(guān)系不會(huì)發(fā)生變化

用戶線程進(jìn)入安全區(qū)域之后會(huì)意識(shí)到自己進(jìn)入了安全區(qū)域,當(dāng)要出安全區(qū)域時(shí)先判斷GC操作是否完成如果沒(méi)有就會(huì)等待直到完成

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容