JVM垃圾回收机制总结
對(duì)于垃圾回收機(jī)制我先拋出三個(gè)問題:
①哪些內(nèi)存需要回收?
②什么時(shí)候回收?
③如何回收?
下面我們主要針對(duì)這三個(gè)問題來研究JVM GC
一、哪些內(nèi)存需要回收?
1.JAVA使用可達(dá)性分析法來判斷對(duì)象是否需要回收。
這個(gè)算法的基本思路是通過一系列稱為“GC ROOTS”的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開始向下搜索,搜索所走過的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到GC ROOTS沒有任何引用鏈的話,則此對(duì)象不可用。可回收。
GC ROOTS對(duì)象包括以下幾種:
①虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象
②方法區(qū)中類靜態(tài)屬性引用的對(duì)象
③方法區(qū)中常量引用的對(duì)象
④本地方法棧JNI引用的對(duì)象
2.對(duì)象在作可達(dá)性分析后如果沒有與任何GC ROOTS關(guān)聯(lián)那么將會(huì)被標(biāo)記篩選,如果它覆蓋了finalize()方法則它將會(huì)被放置在一個(gè)F-Queue隊(duì)列中,并由一個(gè)Finalizer線程去執(zhí)行,如果在finalize方法中成功拯救了自己(將this引用賦值給每個(gè)類變量或者成員變量),則可避免被回收。但是強(qiáng)烈不建議使用對(duì)象的finalize()方法。在這里我只是把我知道的記錄一下。
二、什么時(shí)候回收?
1.安全點(diǎn)
程序在執(zhí)行時(shí)并不是在所有地方都能停下來進(jìn)行GC,只有到達(dá)安全點(diǎn)才能暫停。對(duì)于Safepoint,需要考慮的問題是如何在GC發(fā)生時(shí)讓所有線程都跑到最近的安全點(diǎn)再停頓下來。這里有兩種方案可選:
①搶占式中斷
搶占式中斷不需要線程的執(zhí)行代碼主動(dòng)去配合,在GC發(fā)生時(shí),首先把所有線程全部中斷,如果發(fā)現(xiàn)線程中斷的地方不在安全點(diǎn)上,就恢復(fù)線程,讓它跑到安全點(diǎn)上。
②主動(dòng)式中斷
主動(dòng)式中斷不直接對(duì)線程操作,僅僅設(shè)置一個(gè)標(biāo)志,各個(gè)線程執(zhí)行時(shí)主動(dòng)去輪詢這個(gè)標(biāo)志,發(fā)現(xiàn)中斷標(biāo)志為真時(shí)就自己中斷掛起,輪詢標(biāo)志和安全點(diǎn)是重合的,另外加上創(chuàng)建對(duì)象需要分配內(nèi)存的地方。
2.安全區(qū)域
安全區(qū)域是指在一段代碼中,引用關(guān)系不會(huì)發(fā)生變化,在這個(gè)區(qū)域的任何地方開始GC都是安全的。
線程執(zhí)行到safe region中的代碼時(shí),首先標(biāo)識(shí)自己進(jìn)入safe region,那在這段時(shí)間里JVM要發(fā)起GC時(shí)就不用管那些已經(jīng)標(biāo)識(shí)自己為safe region狀態(tài)的線程了。當(dāng)線程要離開safe region時(shí),檢查系統(tǒng)是否已經(jīng)完成了根節(jié)點(diǎn)枚舉,如果完成了,那線程就繼續(xù)執(zhí)行否則就等待直到可以離開safe region的信號(hào)為止。
三、如何回收?
1.回收算法:
1)標(biāo)記-清除算法
缺點(diǎn):①效率問題,標(biāo)記和清除兩個(gè)過程的效率都不高;②空間問題,清除后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,導(dǎo)致大對(duì)象無法分配而提前出發(fā)GC
2)復(fù)制算法
復(fù)制算法是將內(nèi)存分為大小相等的兩塊,每次只是使用其中的一塊。當(dāng)一塊內(nèi)存使用完之后,將還存活的對(duì)象復(fù)制到另一塊內(nèi)存中,然后清空內(nèi)存。
缺點(diǎn):內(nèi)存容量只使用了一半。
現(xiàn)在的商業(yè)虛擬機(jī)都采用這種方式來回收新生代。使用一塊eden和兩塊survivor區(qū),eden:survivor=8:1,每次只使用eden和一塊survivor,然后將存活對(duì)象復(fù)制到另一塊survivor上。
注意,這里我們不能保證每次回收都只有不多于10%的對(duì)象存活,當(dāng)survivor空間不夠時(shí)需要依賴其他內(nèi)存(老年代)進(jìn)行分配擔(dān)保。
3)標(biāo)記-整理算法
標(biāo)記過程與標(biāo)記-清除算法相同,后續(xù)不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存
4)分代收集算法
針對(duì)不同的內(nèi)存區(qū)域采用不同的回收算法,比如年輕代采用復(fù)制算法,老年代采用標(biāo)記-清除或者標(biāo)記-整理算法。
四、垃圾回收器
1.serial收集器
單線程收集器,年輕代采用復(fù)制收集算法,老年代采用標(biāo)記-整理算法
2.ParNew收集器
是Serial收集器的多線程版本
3.Parallel Scavenge收集器
采用復(fù)制算法的多線程新生代收集器,與ParNew不同的是,其目的是達(dá)到一個(gè)可控制的吞吐量。(吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+垃圾收集時(shí)間))
4.Parallel Old收集器
Parallel Scavenge的老年代版本。
5.CMS收集器
以獲取最短回收時(shí)間為目標(biāo)的收集器,基于標(biāo)記-清除算法
6.G1收集器
特點(diǎn):
①并行與并發(fā)
②分代收集
G1不需要與其他收集器配合,管理整個(gè)GC堆
③空間整合
從整體上來看屬于標(biāo)記-整理算法,從局部看屬于復(fù)制算法,不會(huì)產(chǎn)生內(nèi)存碎片
④可預(yù)測停頓
?
轉(zhuǎn)載于:https://www.cnblogs.com/CLAYJJ/p/8253848.html
總結(jié)
以上是生活随笔為你收集整理的JVM垃圾回收机制总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网飞刷屏神剧 《爱 死亡和机器人》官宣续
- 下一篇: bzoj千题计划213:bzoj2660