☆技術(shù)問答集錦(17)JVM垃圾回收

1 判斷對象是否可回收有幾種方式霹崎?

  1. 引用計(jì)數(shù)算法

優(yōu)點(diǎn):實(shí)現(xiàn)簡單桑驱,判定高效;

缺點(diǎn):很難解決對象之間相互循環(huán)引用的問題脉顿;

  1. 可達(dá)性分析算法

通過一系列"GC Roots"對象作為起始點(diǎn),開始向下搜索点寥,當(dāng)一個(gè)對象到GC Roots沒有任何引用鏈相連時(shí)(從GC Roots到這個(gè)對象不可達(dá))艾疟,則證明該對象是不可用的;

優(yōu)點(diǎn):更加精確和嚴(yán)謹(jǐn)敢辩,可以分析出循環(huán)數(shù)據(jù)結(jié)構(gòu)相互引用的情況蔽莱;

缺點(diǎn):實(shí)現(xiàn)比較復(fù)雜;需要分析大量數(shù)據(jù)责鳍,消耗大量時(shí)間碾褂;分析過程需要GC停頓(引用關(guān)系不能發(fā)生變化),即停頓所有Java執(zhí)行線程(稱為"Stop The World"历葛,是垃圾回收重點(diǎn)關(guān)注的問題)正塌;

2 "GC Roots"對象都包含哪些

  1. 虛擬機(jī)棧 (棧幀中本地變量表)中引用的對象
  2. 方法區(qū)中 類靜態(tài)屬性引用的對象 恤溶;
  3. 方法區(qū)中 常量引用的對象乓诽;
  4. 本地方法棧 JNI(Native方法)中引用的對象

3 Java四種引用類型分別是什么咒程?及存活時(shí)間

  1. 強(qiáng)引用:程序代碼普遍存在的鸠天,類似"Object obj=new Object()";只要強(qiáng)引用還存在帐姻,GC永遠(yuǎn)不會(huì)回收被引用的對象稠集;
  2. 軟引用:描述還有用但并非必需的對象;直到內(nèi)存空間不夠時(shí)(拋出OutOfMemoryError之前)饥瓷,才會(huì)被垃圾回收剥纷;最常用于實(shí)現(xiàn)對內(nèi)存敏感的緩存;SoftReference類實(shí)現(xiàn)呢铆;
  3. 弱引用:用來描述非必需對象晦鞋;只能生存到下一次垃圾回收之前,無論內(nèi)存是否足夠;WeakReference類實(shí)現(xiàn)悠垛;
  4. 虛引用:完全不會(huì)對其生存時(shí)間構(gòu)成影響线定;唯一目的就是能在這個(gè)對象被回收時(shí)收到一個(gè)系統(tǒng)通知;PhantomRenference類實(shí)現(xiàn)确买;

4 Java四種引用使用場景

  1. 強(qiáng)引用-FinalReference

地球人都知道斤讥,但是我講不出來;

  1. 軟引用-SoftReference

創(chuàng)建緩存的時(shí)候拇惋,創(chuàng)建的對象放進(jìn)緩存中周偎,當(dāng)內(nèi)存不足時(shí),JVM就會(huì)回收早先創(chuàng)建的對象撑帖。PS:圖片編輯器,視頻編輯器之類的軟件可以使用這種思路澳眷。

軟引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用胡嘿,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機(jī)就會(huì)把這個(gè)軟引用加入到與之關(guān)聯(lián)的引用隊(duì)列中钳踊。

  1. 弱引用-WeakReference

Java源碼中的java.util.WeakHashMap中的key就是使用弱引用衷敌,一旦不需要某個(gè)引用,JVM會(huì)自動(dòng)處理它拓瞪,這樣就不需要做其它操作缴罗。

弱引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對象被垃圾回收祭埂,Java虛擬機(jī)就會(huì)把這個(gè)弱引用加入到與之關(guān)聯(lián)的引用隊(duì)列中面氓。

  1. 虛引用-PhantomReference

主要用來跟蹤對象被垃圾回收器回收的活動(dòng)。虛引用的回收機(jī)制跟弱引用差不多蛆橡,但是它被回收之前舌界,會(huì)被放入ReferenceQueue中。注意哦泰演,其它引用是被JVM回收后才被傳入ReferenceQueue中的呻拌。由于這個(gè)機(jī)制,所以虛引用大多被用于引用銷毀前的處理工作睦焕。

程序可以通過判斷引用隊(duì)列中是否已經(jīng)加入了虛引用藐握,來了解被引用的對象是否將要被垃圾回收。如果程序發(fā)現(xiàn)某個(gè)虛引用已經(jīng)被加入到引用隊(duì)列垃喊,那么就可以在所引用的對象的內(nèi)存被回收之前采取必要的行動(dòng)猾普。

對象銷毀前的一些操作,比如說資源釋放等缔御。Object.finalize()雖然也可以做這類動(dòng)作抬闷,但是這個(gè)方式即不安全又低效。

5 JVM如何進(jìn)行對象標(biāo)記

  1. 第一次標(biāo)記:在可達(dá)性分析后發(fā)現(xiàn)到GC Roots沒有任何引用鏈相連時(shí),被第一次標(biāo)記笤成;并且進(jìn)行一次篩選:此對象是否必要執(zhí)行finalize()方法评架;沒有必要執(zhí)行的情況,則標(biāo)記對象已死炕泳;有必要執(zhí)行的情況纵诞,則對象被放入F-Queue隊(duì)列中;
  2. 第二次標(biāo)記:GC將對F-Queue隊(duì)列中的對象進(jìn)行第二次小規(guī)模標(biāo)記培遵;finalize()方法是對象逃脫死亡的最后一次機(jī)會(huì)浙芙;一個(gè)對象的finalize()方法只會(huì)被系統(tǒng)自動(dòng)調(diào)用一次,經(jīng)過finalize()方法逃脫死亡的對象籽腕,第二次不會(huì)再調(diào)用嗡呼;

6 為何不建議使用finalize()方法

因?yàn)槠鋱?zhí)行的時(shí)間不確定,甚至是否被執(zhí)行也不確定(Java程序的不正常退出)皇耗,而且運(yùn)行代價(jià)高昂南窗,無法保證各個(gè)對象的調(diào)用順序(甚至有不同線程中調(diào)用);如果需要"釋放資源"郎楼,可以定義顯式的終止方法万伤,并在"try-catch-finally"的finally{}塊中保證及時(shí)調(diào)用;

如果有關(guān)鍵資源呜袁,必須顯式的終止方法敌买;一般情況下,應(yīng)盡量避免使用它阶界,甚至可以忘掉它虹钮;

7 什么是安全點(diǎn),為什么需要

運(yùn)行中荐操,非常多的指令都會(huì)導(dǎo)致引用關(guān)系變化芜抒;如果為這些指令都生成對應(yīng)的OopMap,需要的空間成本太高托启;

只在特定的位置記錄OopMap引用關(guān)系宅倒,這些位置稱為安全點(diǎn)(Safepoint);

8 如何選定安全點(diǎn)

不能太少屯耸,否則GC等待時(shí)間太長拐迁;也不能太多,否則GC過于頻繁疗绣,增大運(yùn)行時(shí)負(fù)荷线召;

所以,基本上是以程序"是否具有讓程序長時(shí)間執(zhí)行的特征"為標(biāo)準(zhǔn)選定多矮,如:方法調(diào)用缓淹、循環(huán)跳轉(zhuǎn)哈打、循環(huán)的末尾、異常跳轉(zhuǎn)等讯壶;

只有具有這些功能的指令才會(huì)產(chǎn)生Safepoint料仗;

9 如何使Java線程在安全點(diǎn)上停頓

  1. 搶先式中斷(Preemptive Suspension):在GC發(fā)生時(shí),首先中斷所有線程伏蚊;如果發(fā)現(xiàn)不在Safepoint上的線程立轧,就恢復(fù)讓其運(yùn)行到Safepoint上;
  2. 主動(dòng)式中斷(Voluntary Suspension):在GC發(fā)生時(shí)躏吊,不直接操作線程中斷氛改,而是僅簡單設(shè)置一個(gè)標(biāo)志;讓各線程執(zhí)行時(shí)主動(dòng)去輪詢這個(gè)標(biāo)志比伏,發(fā)現(xiàn)中斷標(biāo)志為真時(shí)就自己中斷掛起胜卤;
  3. 而輪詢標(biāo)志的地方和Safepoint是重合的;

10 什么是安全區(qū)域赁项,為什么需要安全區(qū)域

線程不執(zhí)行時(shí)沒有CPU時(shí)間(Sleep或Blocked狀態(tài))瑰艘,無法運(yùn)行到Safepoint上再中斷掛起;

安全區(qū)域:指一段代碼片段中肤舞,引用關(guān)系不會(huì)發(fā)生變化;在這個(gè)區(qū)域中的任意地方開始GC都是安全的均蜜;

11 如何使用安全區(qū)域解決問題

  1. 線程執(zhí)行進(jìn)入Safe Region李剖,首先標(biāo)識(shí)自己已經(jīng)進(jìn)入Safe Region;
  2. 線程被喚醒離開Safe Region時(shí)囤耳,其需要檢查系統(tǒng)是否已經(jīng)完成根節(jié)點(diǎn)枚舉(或整個(gè)GC)篙顺;
  3. 如果已經(jīng)完成,就繼續(xù)執(zhí)行充择;否則必須等待德玫,直到收到可以安全離開Safe Region的信號通知,這樣就不會(huì)影響標(biāo)記結(jié)果椎麦;

12 GC算法:標(biāo)記-清楚優(yōu)缺點(diǎn)

優(yōu)點(diǎn):基于最基礎(chǔ)的可達(dá)性分析算法宰僧,它是最基礎(chǔ)的收集算法;而后續(xù)的收集算法都是基于這種思路并對其不足進(jìn)行改進(jìn)得到的观挎;

缺點(diǎn):效率問題琴儿,標(biāo)記和清除兩個(gè)過程的效率都不高;空間問題嘁捷,標(biāo)記清除后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片造成;這會(huì)導(dǎo)致分配大內(nèi)存對象時(shí),無法找到足夠的連續(xù)內(nèi)存雄嚣;從而需要提前觸發(fā)另一次垃圾收集動(dòng)作晒屎;

13 GC算法:復(fù)制算法優(yōu)缺點(diǎn)

優(yōu)點(diǎn):使得每次都是只對整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收;內(nèi)存分配時(shí)也不用考慮內(nèi)存碎片等問題;實(shí)現(xiàn)簡單鼓鲁,運(yùn)行高效蕴轨;

缺點(diǎn):空間浪費(fèi);效率隨對象存活率升高而變低坐桩;

14 GC算法:HotSpot虛擬機(jī)復(fù)制算法

  1. 將新生代內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間尺棋;
  2. 每次使用Eden和其中一塊Survivor;
  3. 當(dāng)回收時(shí)绵跷,將Eden和使用中的Survivor中還存活的對象一次性復(fù)制到另外一塊Survivor膘螟;
  4. 而后清理掉Eden和使用過的Survivor空間;
  5. 后面就使用Eden和復(fù)制到的那一塊Survivor空間碾局,重復(fù)步驟3荆残;

默認(rèn)Eden:Survivor=8:1,即每次可以使用90%的空間净当,只有一塊Survivor的空間被浪費(fèi)内斯;

15 什么是分配擔(dān)保

如果另一塊Survivor空間沒有足夠空間存放上一次新生代收集下來的存活對象時(shí),這些對象將直接通過分配擔(dān)保機(jī)制(Handle Promotion)進(jìn)入老年代像啼;

16 GC算法:標(biāo)記-整理優(yōu)缺點(diǎn)

優(yōu)點(diǎn):不會(huì)產(chǎn)生內(nèi)存碎片俘闯;

缺點(diǎn):增加了對存活對象需要整理的過程,效率更低忽冻;

17 分代收集算法

"分代收集"(Generational Collection)算法結(jié)合不同的收集算法處理不同區(qū)域真朗。

新生代:每次垃圾收集都有大批對象死去,只有少量存活僧诚;所以可采用復(fù)制算法遮婶;

老年代:對象存活率高,沒有額外的空間可以分配擔(dān)保湖笨;使用"標(biāo)記-清理"或"標(biāo)記-整理"算法旗扑;

優(yōu)點(diǎn):根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ǎ?/p>

缺點(diǎn):仍然不能控制每次垃圾收集的時(shí)間;

18 G1垃圾收集算法

19 JVM有哪些收集器慈省?分別用于哪些代臀防?

JDK7/8后,HotSpot虛擬機(jī)所有收集器及組合(連線)辫呻,如下圖:

JVM收集器

新生代收集器:Serial清钥、ParNew、Parallel Scavenge放闺;
老年代收集器:Serial Old祟昭、Parallel Old、CMS怖侦;
整堆收集器:G1篡悟;

20 Serial收集器

新生代谜叹、復(fù)制算法、單線程收集搬葬;

缺點(diǎn):進(jìn)行垃圾收集時(shí)份招,必須暫停所有工作線程摸航,直到完成;即會(huì)"Stop The World";

Serial/Serial Old組合收集器運(yùn)行示意圖如下

Serial/Serial Old組合

21 ParNew收集器

新生代励背、復(fù)制算法替饿、多線程收集怜珍;

缺點(diǎn):進(jìn)行垃圾收集時(shí)瞬测,必須暫停所有工作線程,直到完成床三;即會(huì)"Stop The World"一罩;

ParNew/Serial Old組合收集器運(yùn)行示意圖如下

ParNew/Serial Old組合

22 Parallel Scavenge收集器

新生代、復(fù)制算法撇簿、多線程收集聂渊;

CMS等收集器的關(guān)注點(diǎn)是盡可能地縮短垃圾收集時(shí)用戶線程的停頓時(shí)間;而Parallel Scavenge收集器的目標(biāo)則是達(dá)一個(gè)可控制的吞吐量(Throughput)四瘫;

23 Serial Old收集器

老年代汉嗽、"標(biāo)記-整理"算法(還有壓縮,Mark-Sweep-Compact)找蜜、單線程收集诊胞;

24 Parallel Old收集器

老年代、"標(biāo)記-整理"算法(還有壓縮锹杈,Mark-Sweep-Compact)、多線程收集迈着;

25 CMS收集器

老年代竭望、"標(biāo)記-清除"算法(不進(jìn)行壓縮操作,產(chǎn)生內(nèi)存碎片)裕菠、并發(fā)收集咬清、低停頓

CMS收集器運(yùn)行示意圖如下

CMS收集器

整個(gè)過程中耗時(shí)最長的并發(fā)標(biāo)記和并發(fā)清除都可以與用戶線程一起工作;所以總體上說奴潘,CMS收集器的內(nèi)存回收過程與用戶線程一起并發(fā)執(zhí)行旧烧;

CMS收集器3個(gè)明顯的缺點(diǎn)

  1. 對CPU資源非常敏感;
  2. 無法處理浮動(dòng)垃圾画髓,可能出現(xiàn)"Concurrent Mode Failure"失斁蚣簟;
  3. 產(chǎn)生大量內(nèi)存碎片奈虾;

26 G1收集器

27 JVM如何進(jìn)行對象內(nèi)存分配

在堆上分配(JIT編譯優(yōu)化后可能在棧上分配)夺谁,主要在新生代的Eden區(qū)中分配廉赔;

如果啟用了本地線程分配緩沖,將線程優(yōu)先在TLAB上分配匾鸥;

少數(shù)情況下蜡塌,可能直接分配在老年代中;

分配的細(xì)節(jié)取決于當(dāng)前使用哪種垃圾收集器組合勿负,以及JVM中內(nèi)存相關(guān)參數(shù)設(shè)置馏艾;

28 哪些情況下對象內(nèi)存分配會(huì)直接進(jìn)入老年代

  1. 當(dāng)Eden區(qū)沒有足夠空間進(jìn)行分配時(shí),JVM將發(fā)起一次Minor GC(新生代GC)奴愉;Minor GC時(shí)琅摩,如果發(fā)現(xiàn)存活的對象無法全部放入Survivor空間,只好通過分配擔(dān)保機(jī)制提前轉(zhuǎn)移到老年代躁劣。
  2. 需要大量連續(xù)內(nèi)存空間的Java大對象會(huì)直接進(jìn)入老年代迫吐,容易提前觸發(fā)老年代GC;
  3. 經(jīng)過多次Minor GC账忘,如果年齡達(dá)到一定程度志膀,就晉升到老年代;
  4. 動(dòng)態(tài)對象年齡判定:如果在Survivor空間中相同年齡的所有對象大小總和大于Survivor空間的一半鳖擒,大于或等于該年齡的對象就可以直接進(jìn)入老年代溉浙;

29 方法區(qū)中可回收哪些對象

  1. 廢棄常量:與回收J(rèn)ava堆中對象非常類似;
  2. 無用的類:(1)該類所有實(shí)例都已經(jīng)被回收(即Java椎中不存在該類的任何實(shí)例)蒋荚;(2)加載該類的ClassLoader已經(jīng)被回收戳稽,也即通過引導(dǎo)程序加載器加載的類不能被回收;(3)該類對應(yīng)的java.lang.Class對象沒有在任何地方被引用期升,無法在任何地方通過反射訪問該類的方法惊奇;

30 JDK HotSpot虛擬機(jī)方法區(qū)調(diào)整

  1. 在JDK7中,使用永久代(Permanent Generation)實(shí)現(xiàn)方法區(qū)播赁,這樣就可以不用專門實(shí)現(xiàn)方法區(qū)的內(nèi)存管理颂郎,但這容易引起內(nèi)存溢出問題;
  2. 在JDK8中容为,永久代已被刪除乓序,類元數(shù)據(jù)(Class Metadata)存儲(chǔ)空間直接在本地內(nèi)存中分配;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坎背,一起剝皮案震驚了整個(gè)濱河市替劈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌得滤,老刑警劉巖陨献,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異懂更,居然都是意外死亡湿故,警方通過查閱死者的電腦和手機(jī)阿趁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坛猪,“玉大人脖阵,你說我怎么就攤上這事∈裕” “怎么了命黔?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長就斤。 經(jīng)常有香客問我悍募,道長,這世上最難降的妖魔是什么洋机? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任坠宴,我火速辦了婚禮,結(jié)果婚禮上绷旗,老公的妹妹穿的比我還像新娘喜鼓。我一直安慰自己,他們只是感情好衔肢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布庄岖。 她就那樣靜靜地躺著,像睡著了一般角骤。 火紅的嫁衣襯著肌膚如雪隅忿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天邦尊,我揣著相機(jī)與錄音背桐,去河邊找鬼。 笑死蝉揍,一個(gè)胖子當(dāng)著我的面吹牛牢撼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疑苫,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼纷责!你這毒婦竟也來了捍掺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤再膳,失蹤者是張志新(化名)和其女友劉穎挺勿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喂柒,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡不瓶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年禾嫉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚊丐。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡熙参,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出麦备,到底是詐尸還是另有隱情孽椰,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布凛篙,位于F島的核電站黍匾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏呛梆。R本人自食惡果不足惜锐涯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望填物。 院中可真熱鬧纹腌,春花似錦、人聲如沸融痛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雁刷。三九已至覆劈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沛励,已是汗流浹背责语。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留目派,地道東北人坤候。 一個(gè)月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像企蹭,于是被迫代替她去往敵國和親白筹。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java和C++之間有一堵由內(nèi)存動(dòng)態(tài)分配和垃圾收集技術(shù)所圍成的“高墻”谅摄,墻外面的人想進(jìn)來徒河,墻里面的人想出來。 對象...
    胡二囧閱讀 1,089評論 0 4
  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前送漠,它的class會(huì)被類裝載器裝入方法區(qū)(Permanent區(qū))顽照,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,664評論 0 7
  • 作者:一字馬胡 轉(zhuǎn)載標(biāo)志 【2017-11-12】 更新日志 日期更新內(nèi)容備注 2017-11-12新建文章初版 ...
    beneke閱讀 2,203評論 0 7
  • 來自: Android夢想特工隊(duì)作者: Aaron主頁: http://www.wxtlife.com/原...
    技術(shù)特工隊(duì)閱讀 4,373評論 0 28
  • GC區(qū)域Eden Survivor(from,to), Old Gen和Perm Gen VM區(qū)域總體分兩類,he...
    Fitz_Lee閱讀 416評論 0 0