摘要:但是為了豐富引用的種類,以適應(yīng)各種應(yīng)用,中加入了中引用,但是除了強(qiáng)引用,其生命周期會(huì)有所不同,生存能力遞減。加載該類的已被回收。
GC面臨的問(wèn)題有三個(gè):哪些內(nèi)存需要回收、什么時(shí)候回收和怎么回收
哪些內(nèi)存需要回收,一般有兩種方法
引用計(jì)數(shù)
對(duì)每個(gè)對(duì)象都有個(gè)被引用的次數(shù),單被引用的次數(shù)為0的時(shí)候,就表示對(duì)象需要被回收
引用計(jì)數(shù)的缺點(diǎn)是沒有辦法解決循環(huán)引用導(dǎo)致的內(nèi)存泄露問(wèn)題
可達(dá)性分析
現(xiàn)在主流的GC方法都使用可達(dá)性分析
以GC root為起點(diǎn),遍歷整個(gè)樹(或者圖),如果沒有到達(dá)過(guò)某個(gè)對(duì)象,則表示這個(gè)對(duì)象需要被回收
GC Root表示引用鏈的起點(diǎn),包括函數(shù)調(diào)用棧中引用的對(duì)象、static靜態(tài)變量和常量的引用對(duì)象、方法區(qū)中常量引用的對(duì)象,本地方法棧中JNI引用的對(duì)象
也可以分為棧中的對(duì)象、永久代的對(duì)象、本地方法棧中JNI引用的對(duì)象
object什么時(shí)候會(huì)被回收
一般而言,只要沒有引用指向object,就可以在gc的時(shí)候被回收(老年代需要在Full GC,永久代需要在設(shè)定的幾次Full FC)。但是為了豐富引用的種類,以適應(yīng)各種應(yīng)用,JDK1.2中加入了4中引用,但是除了強(qiáng)引用,其生命周期會(huì)有所不同,生存能力遞減。
強(qiáng)引用(Strong Reference)
即普通引用
軟引用(Soft Reference)
當(dāng)觸發(fā)OutOfMemoryException之前,會(huì)觸發(fā)第二次GC,回收這些Object
弱引用(Weak Reference)
當(dāng)觸發(fā)GC的時(shí)候,回收這些Object
虛引用(Phantom Reference)
對(duì)Object的生存無(wú)意義,當(dāng)Object被回收時(shí),會(huì)觸發(fā)虛引用的通知
對(duì)已object在被回收的時(shí)候,還會(huì)有一個(gè)特例,就是定制Object的finalize方法,使之重新與GC Root關(guān)聯(lián),可以使Object逃脫回收
finalize方法在object被GC的時(shí)候會(huì)被執(zhí)行
但是下次被GC的時(shí)候,不會(huì)再次執(zhí)行finalize方法(finalize方法在生命周期內(nèi)只會(huì)執(zhí)行一次),所以不會(huì)再次逃脫回收
方法區(qū)或者Hotspot的永久代也會(huì)進(jìn)行GC
普通常量池常量只要沒有引用指向它,就可以被回收
類的回收判定需要滿足3個(gè)條件
堆中不存在該類實(shí)例,即沒有指向該類的引用(按照jvm的內(nèi)存布局,類實(shí)例是會(huì)有指向類信息的pointer或者h(yuǎn)andler的。
加載該類的class loader已被回收。(class loader應(yīng)該存在操縱其加載的類的方法,即還存在某種聯(lián)系)
該類對(duì)應(yīng)的java.lang.Class對(duì)象沒有在任何地方被引用,在任何地方無(wú)法通過(guò)反射訪問(wèn)該類的方法(如果存在這種引用,則可以通過(guò)反射的機(jī)制,進(jìn)行訪問(wèn)該類,這會(huì)導(dǎo)致錯(cuò)誤,有點(diǎn)像race condition,持有緩存,內(nèi)容卻被改變了)
由這3個(gè)條件應(yīng)該可以推論出:類實(shí)例、class loader、對(duì)應(yīng)的java.lang.Class類和類信息都存在某種聯(lián)系,使得可以通過(guò)這些東西操縱或者訪問(wèn)類信息。
對(duì)于內(nèi)存怎么回收的問(wèn)題,內(nèi)存的回收算法一般分為三種
標(biāo)記-清除
先對(duì)需要進(jìn)行回收的內(nèi)存進(jìn)行標(biāo)記,然后在進(jìn)行清除
復(fù)制算法
將內(nèi)存分為相等的兩塊,每次只使用其中一塊,當(dāng)當(dāng)前使用的內(nèi)存塊使用完了之后,將存活的對(duì)象復(fù)制到另一內(nèi)存塊
Hotspot將新生代分為一個(gè)Eden和兩個(gè)Survivor區(qū),默認(rèn)比例為8:1:1
minor gc的時(shí)候,將eden去和當(dāng)前survivor區(qū)的存活對(duì)象復(fù)制到另一塊survivor區(qū)
如果survivor區(qū)不足以放置存活的object,使用分配擔(dān)保機(jī)制,部分object將直接進(jìn)入老年代
標(biāo)記-整理
先對(duì)存活的object進(jìn)行標(biāo)記,然后將object進(jìn)行整理(統(tǒng)一往一端移動(dòng)),最后將剩余的內(nèi)存進(jìn)行回收
分代收集
就是將內(nèi)存分為不同的區(qū)域,一般分為新生代和老年代兩部分,然后在不同的部分應(yīng)用不同的收集算法
一般來(lái)說(shuō)新生代使用復(fù)制算法,因?yàn)橐话阒粫?huì)有少量object存活
老年代使用標(biāo)記-清除或者標(biāo)記-整理算法,因?yàn)閷?duì)象存活率高,沒有另外的內(nèi)存進(jìn)行分配擔(dān)保
Hostspot的算法實(shí)現(xiàn)
枚舉根節(jié)點(diǎn)
為了避免race condition的問(wèn)題,這里需要進(jìn)行stop the world的操作,保證一致性
為了提高標(biāo)記的效率,降低stop the world的時(shí)間,商業(yè)vm一般都會(huì)使用準(zhǔn)確式GC,會(huì)使用一些方法記錄下引用的準(zhǔn)確位置,避免全局內(nèi)存掃描
Hostspot使用的是OopMap的數(shù)據(jù)結(jié)構(gòu)來(lái)達(dá)到這個(gè)目的
OopMap的具體使用方法還需要深入了解
安全點(diǎn)
由于能導(dǎo)致OopMap變化的指令非常多,所以Hostspot設(shè)置安全點(diǎn),只有在安全點(diǎn)才會(huì)生成OopMap,這也導(dǎo)致只有在安全點(diǎn)才能停頓下來(lái)進(jìn)行GC
如何使所有線程進(jìn)入安全點(diǎn)的方法有兩個(gè)
搶先式中斷,基本上不用
先把所有線程中斷,如果線程不在安全點(diǎn),則恢復(fù)線程讓它到達(dá)安全點(diǎn)
主動(dòng)式中斷
設(shè)置標(biāo)記位,標(biāo)記是否正在進(jìn)行根節(jié)點(diǎn)枚舉
在安全點(diǎn)輪詢標(biāo)記位
安全區(qū)域
如果線程不運(yùn)行,如sleep或者blocked狀態(tài),安全點(diǎn)就沒法解決問(wèn)題
安全區(qū)域指在這個(gè)區(qū)域內(nèi),代碼引用關(guān)系不會(huì)變化
當(dāng)線程到達(dá)安全區(qū)域時(shí),會(huì)對(duì)自己進(jìn)行標(biāo)記,GC時(shí),就不需要管安全狀態(tài)的線程
當(dāng)線程需要離開安全區(qū)域,需要檢查根節(jié)點(diǎn)枚舉標(biāo)記位
垃圾收集器
Serial收集器
簡(jiǎn)單粗暴的串行收集器
適合內(nèi)存不大,單CPU(可以避免線程交互開銷),對(duì)stop the world不太敏感的client環(huán)境
ParNew收集器
Parallel New Generation,新生代并行收集器
Parallel Scavenge收集器
為控制吞吐量而生
通過(guò)控制stop the world的最大時(shí)間和gc時(shí)間的最大比例來(lái)控制gc時(shí)間,控制吞吐量
也可以使用自適應(yīng)參數(shù)
算法主要控制stop the world的時(shí)間,但是代價(jià)是更頻繁的gc和總體更長(zhǎng)的gc時(shí)間總和
Serial Old收集器
老年代的串行收集器
使用的是標(biāo)記-整體算法
Parallel Old收集器
老年代的并行收集器
和Parallel Scavenge收集器一起使用,應(yīng)用于注重吞吐量和CPU敏感的場(chǎng)合
CMS收集器
Concurrent Mark Sweep,Mark Sweep,基于標(biāo)記-清除算法
分為初始標(biāo)記、并行標(biāo)記、重新標(biāo)記、并發(fā)清除4個(gè)階段
其中初始標(biāo)記和重新標(biāo)記 都會(huì)stop the world
耗時(shí)最長(zhǎng)的并發(fā)標(biāo)記和并發(fā)清除都可以和用戶線程一起運(yùn)行
缺點(diǎn)
并CPU資源非常敏感,并發(fā)情況下,占用部分CPU資源,會(huì)導(dǎo)致吞吐量下降
無(wú)法處理浮動(dòng)垃圾,可能出現(xiàn)“concurrent mode failed”而導(dǎo)致另一次Full GC
浮動(dòng)垃圾,在并發(fā)清理階段出現(xiàn)的垃圾,沒法當(dāng)次GC清除
需要預(yù)留老年代空間,給GC時(shí),用戶程序使用
標(biāo)記-清除算法會(huì)導(dǎo)致內(nèi)存碎片
可以設(shè)置是否在Full GC時(shí)整理內(nèi)存,多少次Full GC整理一次內(nèi)存
G1收集器
Garbage First
優(yōu)點(diǎn)有:
并行與并發(fā)
分代手機(jī)
空間整合
整體來(lái)看是標(biāo)記-整理算法,局部來(lái)看是標(biāo)記-復(fù)制算法
可預(yù)測(cè)的停頓
通過(guò)設(shè)置GC時(shí)間的不得超過(guò)一定比例,幾乎是實(shí)時(shí)Java(RTSJ)垃圾收集器的特征
G1實(shí)現(xiàn)
G1將內(nèi)存分為多個(gè)相等的區(qū)域
老年代、新生代的概念還存在,但是改為了內(nèi)存區(qū)域的集合,而不是固定的區(qū)域
G1跟蹤各個(gè)Region區(qū)域里面垃圾堆積的價(jià)值(即花費(fèi)時(shí)間回收內(nèi)存的性價(jià)比),維護(hù)優(yōu)先列表
由優(yōu)先列表建立回收時(shí)間預(yù)測(cè)模型,優(yōu)先收集性價(jià)比高的垃圾
由于分區(qū)域回收內(nèi)存,G1的區(qū)域之間相互引用,導(dǎo)致可達(dá)性分析耗時(shí)的問(wèn)題相比之前的收集器顯得更加突出了
通過(guò)remember set來(lái)避免全堆掃描
remember set記錄被其它區(qū)域引用的情況(待補(bǔ)充)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65561.html
摘要:堆和方法區(qū)只有在程序運(yùn)行時(shí)才能確定內(nèi)存的使用情況,垃圾回收器所關(guān)注的主要就是這部分內(nèi)存。虛擬機(jī)會(huì)根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控信息,動(dòng)態(tài)調(diào)整比率參數(shù)以提供最合適的停頓時(shí)間或最大的吞吐量。 Tip:內(nèi)容為對(duì)《深入理解Java虛擬機(jī)》(周志明 著)第三章內(nèi)容的總結(jié)和筆記。這是第一次拜讀時(shí)讀到的一些重點(diǎn),做個(gè)分享,也為后面再次閱讀和實(shí)踐做保障。 3.1 概述 程序計(jì)數(shù)器、虛擬機(jī)棧、本地...
摘要:抽時(shí)間重新讀了一遍深入理解一書。驗(yàn)證確保文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)自身的安全。可見性可見性是指當(dāng)一個(gè)線程修改了共享變量的值,其他線程能夠立即得知這個(gè)修改。 抽時(shí)間重新讀了一遍《深入理解JVM》一書。以下為摘錄內(nèi)容。 1 java內(nèi)存區(qū)域 showImg(https://segmentfault.com/img/bVboDgk?w=617&h=365...
摘要:前言本文內(nèi)容基本摘抄自深入理解虛擬機(jī),以供復(fù)習(xí)之用,沒有多少參考價(jià)值。此區(qū)域是唯一一個(gè)在虛擬機(jī)規(guī)范中沒有規(guī)定任何情況的區(qū)域。堆是所有線程共享的內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建。虛擬機(jī)上把方法區(qū)稱為永久代。 前言 本文內(nèi)容基本摘抄自《深入理解Java虛擬機(jī)》,以供復(fù)習(xí)之用,沒有多少參考價(jià)值。想要更詳細(xì)了解請(qǐng)參考原書。 第二章 1.運(yùn)行時(shí)數(shù)據(jù)區(qū)域 showImg(https://segment...
摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡(jiǎn)介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號(hào)作者架構(gòu)師奮斗者掃描主頁(yè)左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無(wú)意間聽到領(lǐng)導(dǎo)們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡(jiǎn)而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...
摘要:執(zhí)行引擎作用執(zhí)行字節(jié)碼,或者執(zhí)行本地方法運(yùn)行時(shí)數(shù)據(jù)區(qū)其實(shí)就是指在運(yùn)行期間,其對(duì)內(nèi)存空間的劃分和分配。 雖是讀書筆記,但是如轉(zhuǎn)載請(qǐng)注明出處https://uestc-dpz.github.io..拒絕伸手復(fù)制黨 JVM Java 虛擬機(jī) Java 虛擬機(jī)(Java virtual machine,JVM)是運(yùn)行 Java 程序必不可少的機(jī)制。JVM實(shí)現(xiàn)了Java語(yǔ)言最重要的特征:即平臺(tái)...
閱讀 1363·2021-09-28 09:43
閱讀 4163·2021-09-04 16:41
閱讀 1928·2019-08-30 15:44
閱讀 3752·2019-08-30 15:43
閱讀 788·2019-08-30 14:21
閱讀 2044·2019-08-30 11:00
閱讀 3330·2019-08-29 16:20
閱讀 1933·2019-08-29 14:21