jvm垃圾回收機(jī)制探析

最近比較粗淺的接觸了一下JVM著角,發(fā)現(xiàn)有很多東西還是非常有意思的长已,并不像之前的印象,覺(jué)得JVM相關(guān)的東西生澀難懂鸣驱。本文主要記錄這段時(shí)間內(nèi)對(duì)JVM的接觸泛鸟,主要包括這么幾個(gè)內(nèi)容:

  • JVM結(jié)構(gòu)及內(nèi)存管理機(jī)制

  • JVM垃圾回收常見(jiàn)算法

  • 各種垃圾回收器對(duì)比分析

  • 垃圾回收器參數(shù)匯總

1. JVM組成結(jié)構(gòu)

JVM主要由3部分組成,分別是類(lèi)加載子系統(tǒng)(ClassLoader)踊东,執(zhí)行引擎(Execute Engine)北滥,運(yùn)行數(shù)據(jù)區(qū)域(Runtime Data Area)刚操。

1.1 類(lèi)加載器

類(lèi)加載器負(fù)責(zé)對(duì)Class文件的裝載工作,JVM內(nèi)部對(duì)ClassLoader也有一套完整的體系結(jié)構(gòu)再芋,ClassLoader主要分為以下幾種:

  • Bootstrap ClassLoader
    啟動(dòng)類(lèi)加載器菊霜,Classloader體系的根節(jié)點(diǎn),其他ClassLoader都是通過(guò)直接或間接繼承至它济赎,它在JVM啟動(dòng)時(shí)加載鉴逞,主要加載<JAVA_HOME>\lib,或是-Xbootclasspath參數(shù)指定的路徑中的司训,并且可以被虛擬機(jī)識(shí)別(僅僅按照文件名識(shí)別的)的類(lèi)庫(kù)到虛擬機(jī)內(nèi)存中构捡。

  • Extension ClassLoader
    擴(kuò)展類(lèi)加載器,繼承于Bootstrap壳猜,主要負(fù)責(zé)加載<JAVA_HOME>\lib\ext目錄中的勾徽,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類(lèi)庫(kù)。

  • Application ClassLoader
    應(yīng)用程序類(lèi)加載器统扳,繼承至擴(kuò)展類(lèi)加載器喘帚,主要負(fù)責(zé)加載ClassPath路徑上的類(lèi)庫(kù),如果應(yīng)用程序沒(méi)有自定義自己類(lèi)加載器咒钟,則這個(gè)就是默認(rèn)的類(lèi)加載器吹由。

類(lèi)加載器采用雙親委派模型工作,如果一個(gè)類(lèi)加載器收到一個(gè)類(lèi)加載的請(qǐng)求盯腌,它首先將這個(gè)請(qǐng)求委派給父類(lèi)加載器去完成溉知,每一個(gè)層次類(lèi)加載器都是如此,則所有的類(lèi)加載請(qǐng)求都會(huì)傳送到頂層的啟動(dòng)類(lèi)加載器腕够,只有父加載器無(wú)法完成這個(gè)加載請(qǐng)求(即它的搜索范圍中沒(méi)有找到所要的類(lèi)),子類(lèi)才嘗試加載舌劳。這樣做的好處有兩點(diǎn):1)可以避免重復(fù)加載帚湘,2)安全角度考慮,防止用戶(hù)自定義類(lèi)加載器替代Java的核心API甚淡。

1.2 運(yùn)行數(shù)據(jù)區(qū)

運(yùn)行數(shù)據(jù)區(qū)實(shí)際上就是JVM的內(nèi)存管理區(qū)大诸,它主要分為5個(gè)部分,分別是:

  • 方法區(qū)(Method Area)
    方法區(qū)主要存放類(lèi)信息贯卦,類(lèi)的靜態(tài)變量资柔,常量,屬性撵割,方法等信息贿堰。

  • 堆(heap)
    所有通過(guò)new操作創(chuàng)建的對(duì)象的內(nèi)存都在堆中分配。堆又被劃分為新生代(Young Generation)和舊生代(Tenured Generation)啡彬。新生代又被進(jìn)一步劃分為Eden和Survivor區(qū)羹与,最后Survivor由From和To組成故硅,新建的對(duì)象都是用新生代的Eden分配內(nèi)存,Eden空間不足的時(shí)候纵搁,會(huì)把存活的對(duì)象轉(zhuǎn)移到Survivor中吃衅,新生代大小可以由-Xmn來(lái)控制,也可以用-XX:SurvivorRatio來(lái)控制Eden和Survivor的比例舊生代腾誉。eden,from ,to的默認(rèn)比例是8:1:1徘层。

  • 棧(Stack)
    每個(gè)線(xiàn)程執(zhí)行每個(gè)方法的時(shí)候都會(huì)在棧中申請(qǐng)一個(gè)棧幀,每個(gè)棧幀包括局部變量區(qū)和操作數(shù)棧利职,用于存放此次方法調(diào)用過(guò)程中的臨時(shí)變量惑灵、參數(shù)和中間結(jié)果

  • 程序計(jì)數(shù)器(Program Counter Register)

  • 本地方法棧(Native Method Stack)
    用于支持native方法的執(zhí)行,存儲(chǔ)了每個(gè)native方法調(diào)用的狀態(tài)眼耀。

2. JVM垃圾回收算法

JVM垃圾回收要經(jīng)過(guò)兩個(gè)主要過(guò)程英支,垃圾的收集和垃圾的回收,對(duì)于垃圾收集哮伟,主要有以下兩種算法:

2.1 垃圾收集

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

在JDK1.2之前干花,使用的是引用計(jì)數(shù)器算法,即當(dāng)這個(gè)類(lèi)被加載到內(nèi)存以后楞黄,就會(huì)產(chǎn)生方法區(qū)池凄,堆棧、程序計(jì)數(shù)器等一系列信息鬼廓,當(dāng)創(chuàng)建對(duì)象的時(shí)候肿仑,為這個(gè)對(duì)象在堆棧空間中分配對(duì)象碎税,同時(shí)會(huì)產(chǎn)生一個(gè)引用計(jì)數(shù)器尤慰,同時(shí)引用計(jì)數(shù)器+1,當(dāng)有新的引用的時(shí)候雷蹂,引用計(jì)數(shù)器繼續(xù)+1伟端,而當(dāng)其中一個(gè)引用銷(xiāo)毀的時(shí)候,引用計(jì)數(shù)器-1匪煌,當(dāng)引用計(jì)數(shù)器被減為零的時(shí)候责蝠,標(biāo)志著這個(gè)對(duì)象已經(jīng)沒(méi)有引用了,可以回收了萎庭!
霜医,但是隨著業(yè)務(wù)的發(fā)展,很快出現(xiàn)了一個(gè)問(wèn)題當(dāng)我們的代碼出現(xiàn)下面的情形時(shí)驳规,該算法將無(wú)法適應(yīng):
ObjA.obj = ObjB
ObjB.obj = ObjA
這樣的代碼會(huì)產(chǎn)生如下引用情形 objA指向objB肴敛,而objB又指向objA,這樣當(dāng)其他所有的引用都消失了之后达舒,objA和objB還有一個(gè)相互的引用值朋,也就是說(shuō)兩個(gè)對(duì)象的引用計(jì)數(shù)器各為1叹侄,而實(shí)際上這兩個(gè)對(duì)象都已經(jīng)沒(méi)有額外的引用,已經(jīng)是垃圾了昨登。

2.1.2 根搜索算法

根搜索算法是從離散數(shù)學(xué)中的圖論引入的趾代,程序把所有的引用關(guān)系看作一張圖,從一個(gè)節(jié)點(diǎn)GC ROOT開(kāi)始丰辣,尋找對(duì)應(yīng)的引用節(jié)點(diǎn)撒强,找到這個(gè)節(jié)點(diǎn)以后,繼續(xù)尋找這個(gè)節(jié)點(diǎn)的引用節(jié)點(diǎn)笙什,當(dāng)所有的引用節(jié)點(diǎn)尋找完畢之后飘哨,剩余的節(jié)點(diǎn)則被認(rèn)為是沒(méi)有被引用到的節(jié)點(diǎn),即無(wú)用的節(jié)點(diǎn)琐凭。
目前java中可作為GC Root的對(duì)象有:
1芽隆、 虛擬機(jī)棧中引用的對(duì)象(本地變量表)
2、 方法區(qū)中靜態(tài)屬性引用的對(duì)象
3统屈、 方法區(qū)中常量引用的對(duì)象
4胚吁、 本地方法棧中引用的對(duì)象(Native對(duì)象)

2.2 垃圾回收算法

對(duì)于收集到的垃圾,JVM是采用什么算法進(jìn)行回收的呢愁憔?主要有這么幾種:

  • 標(biāo)記-清除算法
  • 復(fù)制算法
  • 標(biāo)記-整理算法

2.2.1 標(biāo)記清除算法

標(biāo)記-清除算法采用從根集合進(jìn)行掃描腕扶,對(duì)存活的對(duì)象對(duì)象標(biāo)記,標(biāo)記完畢后吨掌,再掃描整個(gè)空間中未被標(biāo)記的對(duì)象半抱,進(jìn)行回收,如圖所示膜宋。
標(biāo)記-清除算法不需要進(jìn)行對(duì)象的移動(dòng)窿侈,并且僅對(duì)不存活的對(duì)象進(jìn)行處理,在存活對(duì)象比較多的情況下極為高效激蹲,但由于標(biāo)記-清除算法直接回收不存活的對(duì)象棉磨,因此會(huì)造成內(nèi)存碎片!


標(biāo)記清除算法
標(biāo)記清除算法

2.2.2 復(fù)制算法

復(fù)制算法采用從根集合掃描学辱,并將存活對(duì)象復(fù)制到一塊新的,沒(méi)有使用過(guò)的空間中环形,這種算法當(dāng)控件存活的對(duì)象比較少時(shí)策泣,極為高效,但是帶來(lái)的成本是需要一塊內(nèi)存交換空間用于進(jìn)行對(duì)象的移動(dòng)


復(fù)制算法
復(fù)制算法

2.2.3 標(biāo)記整理算法

標(biāo)記-整理算法采用標(biāo)記-清除算法一樣的方式進(jìn)行對(duì)象的標(biāo)記抬吟,但在清除時(shí)不同萨咕,在回收不存活的對(duì)象占用的空間后,會(huì)將所有的存活對(duì)象往左端空閑空間移動(dòng)火本,并更新對(duì)應(yīng)的指針危队。標(biāo)記-整理算法是在標(biāo)記清除算法的基礎(chǔ)上聪建,又進(jìn)行了對(duì)象的移動(dòng),因此成本更高茫陆,但是卻解決了內(nèi)存碎片的問(wèn)題金麸。


標(biāo)記整理算法
標(biāo)記整理算法

3. JVM 常見(jiàn)垃圾回收器

為了達(dá)到最優(yōu)效果,JVM分別針對(duì)新生代和舊生代實(shí)現(xiàn)了不同的垃圾回收器簿盅。如圖:


垃圾回收器
垃圾回收器

3.1 串行回收器(Serial)

Serial收集器是歷史最悠久的一個(gè)回收器挥下,JDK1.3之前廣泛使用這個(gè)收集器,目前也是ClientVM下 ServerVM 4核4GB以下機(jī)器的默認(rèn)垃圾回收器桨醋。串行收集器并不是只能使用一個(gè)CPU進(jìn)行收集棚瘟,而是當(dāng)JVM需要進(jìn)行垃圾回收的時(shí)候,需要中斷所有的用戶(hù)線(xiàn)程喜最,知道它回收結(jié)束為止偎蘸,因此又號(hào)稱(chēng)“Stop The World”的垃圾回收器。

3.2 ParNew回收器

ParNew收集器其實(shí)就是多線(xiàn)程版本的Serial收集器瞬内,同樣有
Stop The World的問(wèn)題迷雪,他是多CPU模式下的首選回收器(該回收器在單CPU的環(huán)境下回收效率遠(yuǎn)遠(yuǎn)低于Serial收集器,所以一定要注意場(chǎng)景哦)遂鹊,也是Server模式下的默認(rèn)收集器振乏。

3.3 ParallelScavenge

ParallelScavenge又被稱(chēng)為是吞吐量?jī)?yōu)先的收集器。

3.4 SerialOld

SerialOld是舊生代Client模式下的默認(rèn)收集器秉扑,單線(xiàn)程執(zhí)行慧邮;在JDK1.6之前也是ParallelScvenge回收新生代模式下舊生代的默認(rèn)收集器,同時(shí)也是并發(fā)收集器CMS回收失敗后的備用收集器舟陆。

3.5 ParallelOld

ParallelOld是老生代并行收集器的一種误澳,使用標(biāo)記整理算法、是老生代吞吐量?jī)?yōu)先的一個(gè)收集器秦躯。這個(gè)收集器是JDK1.6之后剛引入的一款收集器忆谓,早期沒(méi)有ParallelOld之前,吞吐量?jī)?yōu)先的收集器老生代只能使用串行回收收集器踱承,大大的拖累了吞吐量?jī)?yōu)先的性能倡缠,自從JDK1.6之后,才能真正做到較高效率的吞吐量?jī)?yōu)先茎活。

3.6 CMS

CMS又稱(chēng)響應(yīng)時(shí)間優(yōu)先(最短回收停頓)的回收器昙沦,使用并發(fā)模式回收垃圾,使用標(biāo)記-清除算法载荔,CMS對(duì)CPU是非常敏感的盾饮,它的回收線(xiàn)程數(shù)=(CPU+3)/4,因此當(dāng)CPU是2核的實(shí)惠,回收線(xiàn)程將占用的CPU資源的50%丘损,而當(dāng)CPU核心數(shù)為4時(shí)僅占用25%普办。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市徘钥,隨后出現(xiàn)的幾起案子衔蹲,更是在濱河造成了極大的恐慌,老刑警劉巖吏饿,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踪危,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡猪落,警方通過(guò)查閱死者的電腦和手機(jī)贞远,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)笨忌,“玉大人蓝仲,你說(shuō)我怎么就攤上這事」倨#” “怎么了袱结?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)途凫。 經(jīng)常有香客問(wèn)我垢夹,道長(zhǎng),這世上最難降的妖魔是什么维费? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任果元,我火速辦了婚禮,結(jié)果婚禮上犀盟,老公的妹妹穿的比我還像新娘而晒。我一直安慰自己,他們只是感情好阅畴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布倡怎。 她就那樣靜靜地躺著,像睡著了一般贱枣。 火紅的嫁衣襯著肌膚如雪监署。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天纽哥,我揣著相機(jī)與錄音焦匈,去河邊找鬼。 笑死昵仅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播摔笤,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼够滑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了吕世?” 一聲冷哼從身側(cè)響起彰触,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎命辖,沒(méi)想到半個(gè)月后况毅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尔艇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年尔许,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片终娃。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幼驶,死狀恐怖统诺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤缭贡,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站灿椅,受9級(jí)特大地震影響殊者,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蕊退,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一郊楣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咕痛,春花似錦痢甘、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至腔丧,卻和暖如春放椰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背愉粤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工砾医, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衣厘。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓如蚜,卻偏偏與公主長(zhǎng)得像压恒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子错邦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

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

  • 1.什么是垃圾回收探赫? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡(jiǎn)欲明心閱讀 89,484評(píng)論 17 311
  • 這篇文章是我之前翻閱了不少的書(shū)籍以及從網(wǎng)絡(luò)上收集的一些資料的整理,因此不免有一些不準(zhǔn)確的地方撬呢,同時(shí)不同JDK版本的...
    高廣超閱讀 15,599評(píng)論 3 83
  • 1.一些概念 1.1.數(shù)據(jù)類(lèi)型 Java虛擬機(jī)中伦吠,數(shù)據(jù)類(lèi)型可以分為兩類(lèi):基本類(lèi)型和引用類(lèi)型』昀梗基本類(lèi)型的變量保存原始...
    落落落落大大方方閱讀 4,538評(píng)論 4 86
  • JVM內(nèi)存區(qū)域 JVM將其管理的內(nèi)存分為若干數(shù)據(jù)區(qū)域毛仪,這些數(shù)據(jù)區(qū)域分布情況如下圖所示: 程序計(jì)數(shù)器:一塊較小內(nèi)存區(qū)...
    luoxn28閱讀 696評(píng)論 0 0
  • 兒子愛(ài)哭。 任何場(chǎng)地芯勘,任何時(shí)間箱靴,任何情景只要“委屈”他都能淚如泉涌。 都說(shuō)女人是水做的借尿,那么他就是冰雕的刨晴。 柔如清...
    追夢(mèng)CEO閱讀 607評(píng)論 2 2