溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

java中堆和垃圾回收機(jī)制的介紹

發(fā)布時(shí)間:2020-07-03 14:55:53 來(lái)源:億速云 閱讀:223 作者:元一 欄目:web開(kāi)發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)java中堆和垃圾回收機(jī)制的介紹,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

堆通常是一個(gè)可以被看做一棵樹(shù)的數(shù)組對(duì)象。堆中某個(gè)節(jié)點(diǎn)的值總是不大于或不小于其父節(jié)點(diǎn)的值;堆總是一棵完全二叉樹(shù)。將根節(jié)點(diǎn)最大的堆叫做最大堆或大根堆,根節(jié)點(diǎn)最小的堆叫做最小堆或小根堆。常見(jiàn)的堆有二叉堆、斐波那契堆等。堆是非線性數(shù)據(jù)結(jié)構(gòu),相當(dāng)于一維數(shù)組,有兩個(gè)直接后繼。

堆又叫做 “GC堆,"由于現(xiàn)在收集器基本都采用分代收集算法,所以Java堆還可以細(xì)分為:新生代和老年代,比例是1:2;再細(xì)致一點(diǎn)新生代內(nèi)部又劃分為Eden區(qū)、Survivor區(qū),比例為8:1。

下圖顯示了堆的結(jié)構(gòu):

java中堆和垃圾回收機(jī)制的介紹

對(duì)象在堆中內(nèi)存的分配是有嚴(yán)格規(guī)定的,策略為:

  • 對(duì)象優(yōu)先在新生代Eden區(qū)分配內(nèi)存;

  • 大對(duì)象直接進(jìn)老年代,主要是長(zhǎng)字符串和數(shù)組這些需要大量連續(xù)內(nèi)存空間的對(duì)象;

  • 長(zhǎng)期存活的對(duì)象進(jìn)入老年代。Eden區(qū)內(nèi)存不夠時(shí),JVM發(fā)起一次MinorGC,對(duì)象的年齡加一,默認(rèn)對(duì)象年齡到15時(shí)進(jìn)入老年代;

  • 動(dòng)態(tài)年齡判定。相同年齡所有對(duì)象大小的總和大于 Survivor 空間的一半,大于等于該年齡的對(duì)象進(jìn)入老年代

新生代 GC指Minor GC,在新生代的進(jìn)行垃圾回收,頻繁且快。 老年代 GC(Major GC/Full GC)在老年代進(jìn)行垃圾回收,通常伴隨著至少一次的minor gc。速度慢。Full GC在如下幾種情況下都會(huì)被觸發(fā):

  1. 老年代空間不足;

  2. 方法區(qū)空間不足;

  3. 調(diào)用System.gc(),建議JVM進(jìn)行full gc;

  4. 長(zhǎng)期存活的對(duì)象轉(zhuǎn)入老年代,空間不足;

  5. 沒(méi)有足夠的連續(xù)空間分配給大對(duì)象;

  6. 新生代垃圾回收存活的對(duì)象太多,S1放不下,老年代擔(dān)保空間不足,擔(dān)保空間指的是老年代最大可用的連續(xù)空間是否大于新生代所有對(duì)象總空間。

堆里面幾乎放了所有的對(duì)象,那我們?cè)趺粗肋@些對(duì)象是否還有用呢?JVM提供了兩種方法來(lái)判定:

  • 引用計(jì)數(shù)法:給對(duì)象添加一個(gè)引用計(jì)數(shù)器,每次被引用,計(jì)數(shù)器值加一,引用失效,計(jì)數(shù)器值減一,當(dāng)引用數(shù)為0時(shí),表示對(duì)象不存活。引用計(jì)數(shù)法無(wú)法解決循環(huán)引用問(wèn)題,周志朋老師書(shū)里面有詳細(xì)的例子,也是比較容易理解的。

  • 可達(dá)性分析法:以 ”GC Roots“對(duì)象為起始點(diǎn),就像是樹(shù)的根節(jié)點(diǎn),向下搜索,搜索走過(guò)的路徑稱為引用鏈,如果一個(gè)對(duì)象到 GC Roots起始點(diǎn)沒(méi)有引用鏈,則此對(duì)象不可達(dá),是需要被回收的。GC Roots是指虛擬機(jī)棧引用的對(duì)象,本地方法棧引用的對(duì)象,方法區(qū)靜態(tài)屬性引用的對(duì)象,方法區(qū)常量引用的對(duì)象。

上面提到了引用,對(duì)象的存活都和引用有關(guān),引用類型又分為強(qiáng)引用,軟引用,弱引用,虛引用。

  • 強(qiáng)引用,new出來(lái)的對(duì)象,垃圾回收器絕不會(huì)回收它;

  • 軟引用,在系統(tǒng)將要發(fā)生OMM前會(huì)回收這些對(duì)象的內(nèi)存;

  • 弱引用,垃圾收集器工作時(shí)只要發(fā)現(xiàn),馬上回收;

  • 虛引用,形同虛設(shè),任何時(shí)候都可能被回收。

實(shí)際上可達(dá)性分析法判定的不可達(dá)對(duì)象不會(huì)馬上回收,對(duì)象真正被回收需要經(jīng)過(guò)兩次標(biāo)記。第一次標(biāo)記就是被判定為不可達(dá)對(duì)象,然后進(jìn)行一次篩選,篩選條件是此對(duì)象是否有必要執(zhí)行finalize()方法。如果沒(méi)有重寫(xiě)finalize()方法或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過(guò),finalize()方法只會(huì)被系統(tǒng)調(diào)用一次。這兩種情況都是”沒(méi)有必要執(zhí)行的“。如果有必要,這個(gè)對(duì)象會(huì)被放在F-Quene隊(duì)列中,由虛擬機(jī)自動(dòng)建立的低優(yōu)先級(jí)的Finalizer線程去執(zhí)行finalize()方法。這期間GC會(huì)對(duì)F-Quene中的對(duì)象進(jìn)行第二次小規(guī)模標(biāo)記,如果對(duì)象依然沒(méi)有被引用,那就會(huì)被回收,沒(méi)有被篩選的對(duì)象不一定被回收。

我們已經(jīng)知道對(duì)象什么時(shí)候被回收了,那如何回收呢?介紹四種最常用的垃圾回收算法:

  • 標(biāo)記-清除:先標(biāo)記需清除的對(duì)象,統(tǒng)一回收----效率不高,會(huì)產(chǎn)生大量不連續(xù)的碎片;

  • 復(fù)制算法:將內(nèi)存分塊,每次只使用一塊,使用完后,將存活的對(duì)象復(fù)制到另一塊上;

  • 標(biāo)記整理:先標(biāo)記存活對(duì)象,然后讓所有存活對(duì)象向一端移動(dòng),直接清理端邊界以外的內(nèi)存;

  • 分代算法,堆分隊(duì)新生代和老年代,新生代每次收集都會(huì)有大量的對(duì)象死去,選擇復(fù)制算法。老年代存活率比較高,且沒(méi)有額外空間進(jìn)行分配擔(dān)保,選擇標(biāo)記清除或者標(biāo)記整理算法。

垃圾收集算法是一種內(nèi)存回收的思想,具體的實(shí)現(xiàn)是垃圾收集器。簡(jiǎn)要介紹下常用的垃圾收集器:

  • serial串行收集器。單線程,垃圾回收的時(shí)候,必須暫停其他工作。新生復(fù)制,老年標(biāo)記整理。簡(jiǎn)單高效;

  • ParNew 收集器。serial的多線程版本;

  • Parallel Scavenge 收集器,復(fù)制算法的多線程收集器。注重吞吐量,cpu運(yùn)行代碼時(shí)間/cpu耗時(shí)總時(shí)間。新生復(fù)制,老年標(biāo)記整理;

  • Serial Old 收集器,老年代版本;

  • Parallel Old 收集器,Parallel Scavenge老年代版本;

  • CMS 收集器,注重最短時(shí)間停頓。并發(fā)收集器,垃圾收集線程與用戶線程(基本上)同時(shí)工作。 標(biāo)記清除算法

關(guān)于java中堆和垃圾回收機(jī)制的介紹就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI