JVM 垃圾回收機(jī)制之堆的分代回收

JVM垃圾回收機(jī)制之堆的分代回收

前言

前文我們了解了Java的GC機(jī)制,對(duì)于堆中的對(duì)象,JVM采用引用計(jì)數(shù)和可達(dá)性分析兩種算法來標(biāo)記對(duì)象是否可以清除,本文中我們還會(huì)了解到JVM將對(duì)分成了不同的區(qū)域,以便于更好的回收對(duì)象。

堆的分代

Java的堆是JVM中最大的一塊內(nèi)存區(qū)域,主要保存Java中各種類的實(shí)例。為了更好的管理堆中各個(gè)對(duì)象的內(nèi)存,包括分配內(nèi)存和回收內(nèi)存。

JVM將堆分成了幾塊區(qū)域:

新生代(Young)

新生代又分為:

Eden

From Survivor

To Survivor

老年代(Old)

其中新生代占堆的1/3空間,老年代占堆的2/3空間。

而新生代中的Eden占新生代的8/10,From Survivor和To Survivor各占新生代的1/10。

堆模型如圖:

從上圖中我們可以看出:堆是由新生代和老年代組成,默認(rèn)情況下,新生代 ( Young ) 與老年代 ( Old ) 的比例為 1:2 。其中,新生代 ( Young ) 又分為 Eden 和 From Survivor 、To Survivor區(qū)域。默認(rèn)情況下,Eden 和from、to的比例為 :8 : 1 : 1 。JVM 每次只會(huì)使用 Eden 和其中的一塊 Survivor 區(qū)域來為對(duì)象服務(wù),所以無論什么時(shí)候,總是有一塊 Survivor 區(qū)域是空閑著的。因此,新生代實(shí)際可用的內(nèi)存空間為 9/10 ( 即90% )的新生代空間。

堆的GC機(jī)制

堆中的GC分為兩種:

Minor GC

Full GC

Minor GC發(fā)生在新生代,采用的算法是復(fù)制算法。

Java中新創(chuàng)建的對(duì)象都在新生代中,當(dāng)對(duì)象被判定為死亡時(shí)(也就是無法訪問),就會(huì)被GC回收內(nèi)存,發(fā)生Minor GC時(shí),會(huì)將Eden和From Survivor區(qū)域中的存活的對(duì)象復(fù)制到To Survivor區(qū)域中,然后將Eden和From survivor區(qū)域進(jìn)行清理。

當(dāng)一個(gè)對(duì)象活過了一次Minor GC后,它的年齡就加1,當(dāng)對(duì)象的年齡達(dá)到了15時(shí),對(duì)象就會(huì)被放入老年代。

Full GC發(fā)生在老年代,采用的是標(biāo)記-清除算法。

標(biāo)記:標(biāo)記的過程其實(shí)就是,遍歷所有的GC Roots,然后將所有GC Roots可達(dá)的對(duì)象標(biāo)記為存活的對(duì)象。

清除:清除的過程將遍歷堆中所有的對(duì)象,將沒有標(biāo)記的對(duì)象全部清除掉。

當(dāng)程序運(yùn)行期間,若可以使用的內(nèi)存被耗盡的時(shí)候,GC線程就會(huì)被觸發(fā)并將程序暫停,隨后將依舊存活的對(duì)象標(biāo)記一遍,最終再將堆中所有沒被標(biāo)記的對(duì)象全部清除掉,接下來便讓程序恢復(fù)運(yùn)行。

標(biāo)記-清除算法存在比較大的缺點(diǎn):

進(jìn)行GC時(shí)需要暫停應(yīng)用程序,所以導(dǎo)致用戶體驗(yàn)變差

會(huì)產(chǎn)生許多不連續(xù)的內(nèi)存空間

所以我們一般會(huì)避免出現(xiàn)Full GC。

JVM參數(shù)

堆的初始大小、新生代、老年代的大小都可以通過JVM的參數(shù)進(jìn)行配置。

下面是一些常用的JVM參數(shù):

-Xms初始堆大小。如:-Xms256m

-Xmx最大堆大小。如:-Xmx512m

-Xmn新生代大小。通常為 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 個(gè) Survivor 空間。實(shí)際可用空間為 = Eden + 1 個(gè) Survivor,即 90%

-Xss線程的堆棧大小

-XX:NewRatio新生代與老年代的比例,如 –XX:NewRatio=2,則新生代占整個(gè)堆空間的1/3,老年代占2/3

-XX:SurvivorRatio新生代中 Eden 與 Survivor 的比值。默認(rèn)值為 8。即 Eden 占新生代空間的 8/10,另外兩個(gè) Survivor 各占 1/10

-XX:PermSize永久代(方法區(qū))的初始大小

-XX:MaxPermSize永久代(方法區(qū))的最大值

-XX:+PrintGCDetails打印 GC 信息

下面是Eclipse的JVM參數(shù)配置方法:

Window --- Preferences --- Java --- Installed JREs --- 點(diǎn)擊Edit

在Default VM arguments中添加參數(shù):

總結(jié)

本文我們學(xué)習(xí)了JVM堆GC的分代機(jī)制,堆分為新生代和老年代,新生代中采用Minor GC,使用的是復(fù)制算法,老年代中采用Full GC,使用的是標(biāo)記-清除算法。

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前,它的class會(huì)被類裝載器裝入方法區(qū)(Permanent區(qū)),執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,852評(píng)論 0 7
  • GC區(qū)域Eden Survivor(from,to), Old Gen和Perm Gen VM區(qū)域總體分兩類,he...
    Fitz_Lee閱讀 498評(píng)論 0 0
  • 作者:一字馬胡 轉(zhuǎn)載標(biāo)志 【2017-11-12】 更新日志 日期更新內(nèi)容備注 2017-11-12新建文章初版 ...
    beneke閱讀 2,332評(píng)論 0 7
  • JVM內(nèi)存區(qū)域 JVM將其管理的內(nèi)存分為若干數(shù)據(jù)區(qū)域,這些數(shù)據(jù)區(qū)域分布情況如下圖所示: 程序計(jì)數(shù)器:一塊較小內(nèi)存區(qū)...
    luoxn28閱讀 780評(píng)論 0 0
  • http://www.cnblogs.com/angeldevil/p/3801189.html值得一看 Clas...
    snail_knight閱讀 1,620評(píng)論 1 0

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