淺析JVM垃圾收集回收機(jī)制

垃圾對(duì)象的判斷

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

對(duì)象創(chuàng)建時(shí),給該對(duì)象實(shí)例分配給一個(gè)變量,該變量計(jì)數(shù)設(shè)置為1。當(dāng)該對(duì)象引用被調(diào)用時(shí),計(jì)數(shù)加1,當(dāng)其他變量不再被該對(duì)象引用賦值而設(shè)置為一個(gè)新值時(shí),對(duì)象實(shí)例的引用計(jì)數(shù)器減1。任何引用計(jì)數(shù)器為0的對(duì)象實(shí)例可以被當(dāng)作垃圾收集。當(dāng)一個(gè)對(duì)象實(shí)例被垃圾收集時(shí),它引用的任何對(duì)象實(shí)例的引用計(jì)數(shù)器減1。

缺點(diǎn):無法檢測出循環(huán)引用。如父對(duì)象有一個(gè)對(duì)子對(duì)象的引用,子對(duì)象反過來引用父對(duì)象。

可達(dá)性分析法

根不可達(dá)即可回收

作為GCRoots的對(duì)象

  • 虛擬機(jī)棧中引用的對(duì)象(棧幀中的局部變量表);
  • 方法區(qū)的類靜態(tài)屬性所引用的對(duì)象
  • 方法區(qū)中常量所引用的對(duì)象
  • 本地方法棧中引用的對(duì)象

垃圾收集算法

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

從GC Roots掃描,對(duì)存活的對(duì)象進(jìn)行標(biāo)記,標(biāo)記完畢后,再掃描整個(gè)空間中未被標(biāo)記的對(duì)象,進(jìn)行回收,會(huì)造成大量內(nèi)存碎片

復(fù)制算法

把可用的對(duì)象從一個(gè)地方拷貝到另一個(gè)地方,原來區(qū)域作為空閑區(qū),適合大量對(duì)象回收的場景,比如新生代的回收。

標(biāo)記-整理算法

在回收不存活的對(duì)象占用的空間后,會(huì)將所有的存活對(duì)象往左端空閑空間移動(dòng),并更新對(duì)應(yīng)的空閑指針

分代收集算法

根據(jù)對(duì)象存活的生命周期將內(nèi)存劃分為若干個(gè)不同的區(qū)域。一般情況下將堆區(qū)劃分為老年代和新生代,在堆區(qū)之外還有一個(gè)代就是永久代。

年輕代:

  1. 所有新生成的對(duì)象首先都是放在年輕代的。
  2. 新生代內(nèi)存按照8:1:1的比例分為一個(gè)eden區(qū)和兩個(gè)survivor(survivor0,survivor1)區(qū)。回收時(shí)先將eden區(qū)存活對(duì)象復(fù)制到一個(gè)survivor0區(qū),然后清空eden區(qū),當(dāng)這個(gè)survivor0區(qū)也存放滿了時(shí),則將eden區(qū)和survivor0區(qū)存活對(duì)象復(fù)制到另一個(gè)survivor1區(qū),然后清空eden和這個(gè)survivor0區(qū),然后將survivor0區(qū)和survivor1區(qū)交換,即保持survivor1區(qū)為空, 如此往復(fù)。
  3. 當(dāng)survivor1區(qū)不足以存放 eden和survivor0的存活對(duì)象時(shí),就將存活對(duì)象直接存放到老年代。若是老年代也滿了就會(huì)觸發(fā)一次Full GC,也就是新生代、老年代都進(jìn)行回收。
  4. 新生代發(fā)生的GC也叫做Minor GC(復(fù)制算法),MinorGC發(fā)生頻率比較高(不一定等Eden區(qū)滿了才觸發(fā))。

老年代:

在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象,就會(huì)被放到年老代中。
內(nèi)存比新生代也大很多(2倍),當(dāng)老年代內(nèi)存滿時(shí)觸發(fā)Major GC即Full GC(標(biāo)記整理算法)

持久代:

用于存放靜態(tài)文件,如Java類、方法等。

1.8中將字符串常量由永久代轉(zhuǎn)移到堆中,并用元空間取代持久代。元空間并不在虛擬機(jī)中,而是使用本地內(nèi)存。
因此,默認(rèn)情況下,元空間的大小僅受本地內(nèi)存限制,但可以通過以下參數(shù)來指定元空間的大小:

  • -XX:MetaspaceSize,初始空間大小,達(dá)到該值就會(huì)觸發(fā)垃圾收集進(jìn)行類型卸載,同時(shí)GC會(huì)對(duì)該值進(jìn)行調(diào)整:如果釋放了大量的空間,就適當(dāng)降低該值;如果釋放了很少的空間,那么在不超過MaxMetaspaceSize時(shí),適當(dāng)提高該值。
  • -XX:MaxMetaspaceSize,最大空間,默認(rèn)是沒有限制的。
  • -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空間容量的百分比,減少為分配空間所導(dǎo)致的垃圾收集
  • -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空間容量的百分比,減少為釋放空間所導(dǎo)致的垃圾收集

垃圾收集器

Serial 收集器

標(biāo)記-復(fù)制。
單線程,一個(gè)CPU或一條收集線程去完成垃圾收集工作,收集時(shí)必須暫停其他所有的工作線程,直到它結(jié)束。

虛擬機(jī)運(yùn)行在Client模式下的默認(rèn)新生代收集器。

ParNew 收集器

ParNew是Serial收集器的多線程版本。Server模式下默認(rèn)新生代收集器,除了Serial收集器之外,只有它能與CMS收集器配合工作。

Parallel Scavenge 收集器

新生代收集器,復(fù)制算法。側(cè)重于達(dá)到一個(gè)可控制的吞吐量,主要適合在后臺(tái)運(yùn)算而不需要太多交互的任務(wù)。

  • -XX:MaxGCPauseMillis 最大垃圾收集停頓時(shí)間
  • -XX:GCTimeRatio 吞吐量大小

Serial Old收集器

標(biāo)記-整理算法。
單線程,是Serial收集器的老年代版本,給Client模式下的虛擬機(jī)使用。

Parallel Old 收集器

java8默認(rèn)Parallel Scavenge+Parallel Old

CMS 收集器

標(biāo)記-清除。
以獲取最短回收停頓時(shí)間為目標(biāo),適用于互聯(lián)網(wǎng)站或者B/S系統(tǒng)的服務(wù)端

  • 初始標(biāo)記(CMS initial mark) -stop the world,標(biāo)記GC Roots直接關(guān)聯(lián)的對(duì)象
  • 并發(fā)標(biāo)記(CMS concurrent mark)
  • 重新標(biāo)記(CMS remark) -stop the world,GC Roots Tracing
  • 并發(fā)清除(CMS concurrent sweep)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。