一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - JVM的垃圾回收算法工作原理詳解

JVM的垃圾回收算法工作原理詳解

2019-06-30 21:06clawhub Java教程

這篇文章主要介紹了JVM的垃圾回收算如何判斷對象是否可以被回收,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,,需要的朋友可以參考下

怎么判斷對象是否可以被回收

共有2種方法,引用計數法和可達性分析

1.引用計數法

所謂引用計數法就是給每一個對象設置一個引用計數器,每當有一個地方引用這個對象時,就將計數器加一,引用失效時,計數器就減一。當一個對象的引用計數器為零時,說明此對象沒有被引用,也就是“死對象”,將會被垃圾回收.

引用計數法有一個缺陷就是無法解決循環引用問題,也就是說當對象A引用對象B,對象B又引用者對象A,那么此時A,B對象的引用計數器都不為零,也就造成無法完成垃圾回收,所以主流的虛擬機都沒有采用這種算法

public classReferenceFindTest{
publicstaticvoidmain(String[] args){
MyObject object1 = new MyObject();
MyObject object2 = new MyObject();
object1.object = object2;
object2.object = object1;
object1 = null;
object2 = null;
}
}

2.可達性算法(引用鏈法)

該算法的思想是:從一個被稱為GC Roots的對象開始向下搜索,如果一個對象到GC Roots沒有任何引用鏈相連時,則說明此對象不可用。

在java中可以作為GC Roots的對象有以下幾種:

  • 虛擬機棧中引用的對象
  • 方法區類靜態屬性引用的對象
  • 方法區常量池引用的對象
  • 本地方法棧JNI引用的對象

雖然這些算法可以判定一個對象是否能被回收,但是當滿足上述條件時,一個對象比不一定會被回收。當一個對象不可達GC Root時,這個對象并不會立馬被回收,而是出于一個死緩的階段,若要被真正的回收需要經歷兩次標記。

如果對象在可達性分析中沒有與GC Root的引用鏈,那么此時就會被第一次標記并且進行一次篩選,篩選的條件是是否有必要執行finalize()方法。當對象沒有覆蓋finalize()方法或者已被虛擬機調用過,那么就認為是沒必要的。

如果該對象有必要執行finalize()方法,那么這個對象將會放在一個稱為F-Queue的對隊列中,虛擬機會觸發一個Finalize()線程去執行,此線程是低優先級的,并且虛擬機不會承諾一直等待它運行完,這是因為如果finalize()執行緩慢或者發生了死鎖,那么就會造成F-Queue隊列一直等待,造成了內存回收系統的崩潰。GC對處于F-Queue中的對象進行第二次被標記,這時,該對象將被移除”即將回收”集合,等待回收。

堆內存分代策略以及意義

策略

JVM的垃圾回收算法工作原理詳解

Java虛擬機將堆內存劃分為新生代、老年戰和永久代,永久代是HotSpaot 虛擬機特有的概念,它采用永久代的方式來實現方法區,其他的虛擬機實現沒有這一概念,而且HotSpot也有取消永久代的趨勢,在JDK 1.7中HotSpot已經開始了“去永久化”,把原本放在永久代的字符串常量池移出。永久代主要存放常量、類信息、靜態變量等數據(移植到方法區),與垃圾回收關系不大,新生代和老年代是垃圾回收的主要區域。

新生代(Young)

新生成的對象優先存放在新生代中,新生代對象朝生夕死,存活率很低,在新生代中,常規應用進行一次垃圾收集-般可以回收70% ~ 95%的空間,回收效率很高。

老年代(OldGenerationn)

在新生代中經歷了多次(具體看虛擬機配置的閥值)GC后仍然存活下來的對象會進入老年代中。老年代中的對象生命周期較長,存活率比較高,在老年代中進行GC的頻率相對而言較低,而且回收的速度也比較慢。

永久代(PermanentGenerationn)

永久代存儲類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據,對這一區域而言,Java虛擬機規范指出可以不進行垃圾收集,一般而言不會進行垃圾回收。

  • Jdk1.6及之前: 有永久代, 常量池1.6在方法區。
  • Jdk1.7: 有永久代,但已經逐步“去永久代”,常量池1.7在堆。
  • Jdk1.8及之后: 無永久代,常量池1.8在元空間。而元空間是直接存在內存中,不在java虛擬機中的,因此元空間依賴于內存大小。當然你也可以自定義元空間大小。

意義

有了內存分代,新創建的對象會在新生代中分配內存,經過多次回收仍然存活下來的對象存放在老年代中,靜態屬性、類信息等存放在永久代中,新生代中的對象存活時間短,只需要在新生代區域中頻繁進行GC,老年代中對象生命周期長,內存回收的頻率相對較低,不需要頻繁進行回收,永久代中回收效果太差, 一般不進行垃圾回收,還可以根據不同年代的特點,采用不同的垃圾收集算法。分代垃圾收集大大提升了垃圾收集效率,這些都是JVM分代的好處。

垃圾回收算法

1.復制算法

復制算法將可用內存按容量劃分為相等的兩部分,然后每次只使用其中的一塊,當一塊內存用完時,就將還存活的對象復制到第二塊內存上,然后一次性清楚完第一塊內存,再將第二塊上的對象復制到第一塊。但是這種方式,內存的代價太高,每次基本上都要浪費一半的內存。

2.標記清除算法

是JVM垃圾回收算法中最古老的一個,該算法共分成兩個階段,第一階段從引用根節點開始標記所有被引用的對象,第二階段遍歷整個堆,清除未被標記的對象。該算法的缺點是需要暫停整個應用,并且在回收以后未使用的空間是不連續,即內存碎片,會影響到存儲。

3.標記整理算法

此算法結合了標記-清楚算法和復制算法的優點,也分為兩個階段,第一階段從引用根節點開始標記所有被引用的對象,第二階段遍歷整個堆,在回收不存活的對象占用的空間后,會將所有的存活對象往左端空閑空間移動,并更新對應的指針。標記-整理算法是在標記-清除算法的基礎上,又進行了對象的移動,因此成本更高,但是卻解決了內存碎片的問題,按順序排放,同時解決了復制算法所需內存空間過大的問題。

4.分代收集

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根據對象存活的生命周期將內存劃分為若干個不同的區域。一般情況下將堆區劃分為老年代(Tenured Generation)和新生代(Young Generation),在堆區之外還有一個代就是永久代(Permanet Generation)。老年代的特點是每次垃圾收集時只有少量對象需要被回收,而新生代的特點是每次垃圾回收時都有大量的對象需要被回收,那么就可以根據不同代的特點采取最適合的收集算法。

a.年輕代回收算法(核心其實就是復制算法)

HotSpot將新生代劃分為三塊,-塊較大的Eden空間和兩塊較小的Survivor空間,默認比例為8: 1: 1。劃分的目的是因為HotSpot采用復制算法來回收新生代,設置這個比例是為了充分利用內存空間,減少浪費。新生成的對象在Eden區分配(大對象除外,大對象直接進入老年代) ,當Eden區沒有足夠的空間進行分配時,虛擬機將發起一次Minor GC。GC開始時,對象只會存在于Eden區和From Survivor區,To Survivor區是空的(作為保留區域)。

GC進行時,Eden區中所有存活的對象都會被復制到To Survivor區,而在FromSurvivor區中,仍存活的對象會根據它們的年齡值決定去向,年齡值達到閥值(默認為15 ,新生代中的對象每熬過一輪垃圾回收年齡值就加1 ,GC分代年齡存儲在對象的header中)的對象會被移到老年代中,沒有達到閥值的對象會被復制到To Survivor區。

接著清空Eden區和From Survivor區,新生代中存活的對象都在To Survivor區。接著, From Survivor區和To Survivor區會交換它們的角色,也就是新的To Survivor區就是上次GC清空的FromSurvivor區,新的From Survivor區就是.上次GC的To Survivor區,總之,不管怎樣都會保證To Survivor區在一輪GC后是空的(其實這就是分代收集算法中的年輕代回收算法,稍后我們會看到)。

GC時當To Survivor區沒有足夠的空間存放上一次新生代收集下來的存活對象時,需要依賴老年代進行分配擔保,將這些對象存放在老年代中。

JVM的垃圾回收算法工作原理詳解

b.老年代回收算法(回收主要以標記-整理為主)

1)在年輕代中經歷了N次垃圾回收后仍然存活的對象,就會被放到年老代中。因此,可以認為年老代中存放的都是一些生命周期較長的對象。

2)內存比新生代也大很多(大概比例是1:2),當老年代內存滿時觸發Major GC即Full GC,Full GC發生頻率比較低,老年代對象存活時間比較長,存活率標記高。

c. 持久代(Permanent Generation)的回收算法

用于存放靜態文件,如Java類、方法等。持久代對垃圾回收沒有顯著影響,但是有些應用可能動態生成或者調用一些class,例如Hibernate 等,在這種時候需要設置一個比較大的持久代空間來存放這些運行過程中新增的類。在該區內很少發生垃圾回收,但是并不代表不發生GC,在這里進行的GC主要是對持久代里的常量池和對類型的卸載。

條件:

1)該類所有的實例都已經被回收,即Java堆中不存在該類的任何實例;

2)加載該類的ClassLoader已經被回收;

3)該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

虛擬機可以對滿足上述3個條件的無用類進行回收,此處僅僅是“可以”,而并不是和對象一樣,不使用了就必然回收!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 韩国办公室激情 | 男同激情视频 | 亚洲AV无码国产精品色午夜情 | 99久久6er热免费精品 | haodiaose在线精品免费视频 | 久久婷婷五月综合色丁香 | 男女肉文高h | 美女私人影院 | 亚洲成人77777 | 香蕉人人超人人超碰超国产 | 亚洲欧美一区二区三区在线观看 | 日本人妖在线 | 青青草视频破解版 | 乌克兰一级毛片9一18 | 天天综合天天色 | 麻豆资源 | 女教师雪白老汉 | 国产亚洲女在线精品 | 无码专区aaaaaa免费视频 | 色男人网 | 亚洲视频第一页 | 欧美日韩看看2015永久免费 | 精品一区二区三区波多野结衣 | 精品无人区麻豆乱码无限制 | 草草剧场 | 国产亚洲福利一区二区免费看 | 亚洲天堂网站在线 | 成人伊人青草久久综合网破解版 | 精品一区二区国语对白 | 91真人毛片一级在线播放 | 日韩操比视频 | www.99精品视频在线播放 | 亚洲美洲国产日产 | 我与白丝同桌的故事h文 | 成人亚洲欧美综合 | 国产成人精视频在线观看免费 | 亚洲精品国产精品精 | 精品国产成人a区在线观看 精品高潮呻吟99AV无码视频 | 国产精品久久久久久久久免费hd | 天天干天天色综合网 | 91香蕉国产 |