Java垃圾回收機制學習筆記

Java運行時數(shù)據(jù)區(qū)域

在這之前先了解JVM運行時的數(shù)據(jù)區(qū)域,分五塊:

程序計數(shù)器

用于表示當前代碼執(zhí)行到第幾行

虛擬機棧

虛擬機棧描述的是 Java 方法執(zhí)行的內存模型:每個方法在執(zhí)行的同時都會創(chuàng)建一個棧幀(Stack Frame,是方法運行時的基礎數(shù)據(jù)結構)用于存儲局部變量表、操作數(shù)棧吠昭、動態(tài)鏈接作瞄、方法出口等信息丑勤。每一個方法從調用直至執(zhí)行完成的過程贤姆,就對應著一個棧幀在虛擬機棧中入棧到出棧的過程沐飘。

本地方法棧

本地方法棧與虛擬機棧所發(fā)揮的作用是非常相似,虛擬機棧對應描述的是Java方法,而本地方法棧則描述的是Native(C++)方法合敦。

方法區(qū)

方法區(qū)與 Java 堆一樣,是各個線程共享的內存區(qū)域豌汇,它用于存儲已被虛擬機加載的類信息幢炸、常量、靜態(tài)變量拒贱、即時編譯器編譯后的代碼等數(shù)據(jù)宛徊。雖然 Java 虛擬機規(guī)范把方法區(qū)描述為堆的一個邏輯部分,但是它卻有一個別名叫做 Non-Heap(非堆)逻澳,目的應該是與 Java 堆區(qū)分開來闸天。
JDK8 之前,Hotspot(虛擬機) 中方法區(qū)的實現(xiàn)是永久代(Perm)斜做,JDK8 開始使用元空間(Metaspace)苞氮,以前永久代所有內容的字符串常量移至堆內存,其他內容移至元空間瓤逼,元空間直接在本地內存分配笼吟。

對于大多數(shù)應用來說,Java 堆是 Java 虛擬機所管理的內存中最大的一塊霸旗。Java 堆是被所有線程共享的一塊內存區(qū)域贷帮,在虛擬機啟動時創(chuàng)建。此內存區(qū)域的唯一目的就是存放對象實例定硝,幾乎所有的對象實例都在這里分配內存皿桑。堆是垃圾收集器管理的主要區(qū)域毫目,因此很多時候也被稱做“GC堆”蔬啡。從內存回收的角度來看,由于現(xiàn)在收集器基本都采用分代收集算法镀虐,所以 Java 堆中還可以細分為:新生代和老年代箱蟆;再細致一點的有 Eden 空間、From Survivor 空間刮便、To Survivor 空間空猜。

很明顯Java垃圾回收主要作用于區(qū)域,而區(qū)域又分為新生代老年代,而網(wǎng)上說的持久代(永久代)其實是存于方法區(qū)中,并且于JDK1.8后以轉移到元空間中(以前永久代所有內容的字符串常量移至堆內存,其他內容移至元空間恨旱,元空間直接在本地內存分配)

再介紹下堆里又劃分2塊區(qū)域,分別是新生代和老年代(對應比例1:2)

新生代

主要存放新生成的對象,新生代的對象一般是朝生夕滅(存活期短),而新生代的區(qū)域又劃分為三個區(qū)域,分別叫Eden, From Survivor,To Survivor(比例對應為8:1:1)
在新生代區(qū)域觸發(fā)的GC叫做Minor GC

老年代

當新生代的對象經(jīng)過一定次數(shù)的回收仍存活(這個次數(shù)為一個規(guī)定的閾值),那么則會由新生代移動到老年代.老年代則會觸發(fā)Full GC(同時清除新生代,老年代,永久代)

如何判斷對象是否為垃圾

1.引用計數(shù)法

給對象加上計數(shù)器,引用+1,失效-1辈毯。當引用數(shù)為0則為內存垃圾

但是引用計數(shù)法存在一個漏洞,那就是無法解決循環(huán)引用的bug(A持有B的引用,B持有A的引用,運用這個方法則導致兩者都無法被回收)因此出現(xiàn)第二種方法

2.可達性分析法

通過GC Roots作為起始點,從這些節(jié)點開始向下搜索搜贤,搜索走過的路徑叫做引用鏈谆沃。當一個對象與任何一個GC Roots沒有引用鏈相連時,就認為該對象是內存垃圾仪芒。
同樣以上面的案例分析(A,B雖然相互持有引用,但沒有被任何一個GC Roots引用,因此仍然被認為是內存垃圾)
而到底什么對象可以作為GC Roots呢,以下對象都可以 :

  • 虛擬機棧(棧幀中的本地變量表)中引用的對象唁影。
  • 方法區(qū)中類靜態(tài)屬性引用的對象耕陷。
  • 方法區(qū)中常量引用的對象。
  • 本地方法棧中JNI(即一般說的Native方法)引用的對象据沈。

Java垃圾回收算法

知道如何判定對象是否為垃圾后就可以制定垃圾回收的策略(算法)了,分為4種

1.標記-清除算法

標記-清除算法采用從根集合(GC Roots)進行掃描哟沫,對存活的對象進行標記,標記完畢后锌介,再掃描整個空間中未被標記的對象嗜诀,進行回收
優(yōu)點: 并沒有移動仍存活對象的內存,對于正在運行的應用進程影響較少
缺點:1 每個對象找一遍導致效率不高
? ? ? ? 2 容易產(chǎn)生大量不連續(xù)內存碎片無法利用

2.復制算法

把內存分成兩半,對象分配內存時只分配到其中一半的區(qū)域,當這一半?yún)^(qū)域內存滿了則把這部分內存整理復制到另一半?yún)^(qū)域,同時把另一半的區(qū)域的內存清空
優(yōu)點:簡單高效(相對于上面的方法只需遍歷內存的一半),不會出現(xiàn)內存碎片
缺點:一半的內存空間無法使用,代價太大

3.標記-整理算法

先標記(標記方法跟第一種方法一樣),然后把存活的對象移向一端,然后再把其余區(qū)域的內存清掉
優(yōu)點:1 相比標記-清除算法不會產(chǎn)生內存碎片
? ? ? ? 2.相比復制算法不會產(chǎn)生空間浪費

4.分代收集算法

其實嚴格來說分代收集算法只是前面3種算法在Java虛擬機中實際的應用:對于新生代內存,采用復制算法,對于老年代內存,采用標記-整理算法

Dalvik與Art虛擬機在垃圾回收算法上的區(qū)別

Dalvik:只能固定一種垃圾回收算法,出廠就固定了
Art:能夠根據(jù)實際情況選擇垃圾回收算法(例如對于正在前臺運行的app采用標記-清除算法,對于轉到后臺運行的app則可以采用標記-整理算法)

觸發(fā)GC的時機

Minor GC觸發(fā)機制:

當年輕代滿時就會觸發(fā)Minor GC,這里的年輕代滿指的是Eden代滿孔祸,Survivor滿不會引發(fā)GC裹虫。

Full GC觸發(fā)機制:

(1)調用System.gc時,系統(tǒng)建議執(zhí)行Full GC融击,但是不必然執(zhí)行
(2)老年代空間不足
(3)方法區(qū)空間不足
(4)通過Minor GC后進入老年代的大小大于老年代的可用內存
(5)由Eden區(qū)筑公、survivor space1(From Space)區(qū)向survivor space2(To Space)區(qū)復制時,對象大小大于To Space可用內存尊浪,則把該對象轉存到老年代匣屡,且老年代的可用內存小于該對象大小

堆的垃圾回收工作流程

新生成的對象會在Eden區(qū)中存在,當Eden內存已滿把Eden無效的數(shù)據(jù)清除,存活的數(shù)據(jù)(沒能釋放內存的數(shù)據(jù))移到From Survivor,假如From Survivor內存滿了則把Eden 和From Survivor的內存整理移到To Survivor中,如此反復(假如其中一個Survivor并不足以承載Eden+另一個Survivor的內存時直接轉移到老年代區(qū)域),在Survivor中只要一次GC沒把對象內存清掉給內存計數(shù)就會+1,當這個計數(shù)達到一定閾值會從新生代區(qū)域轉移到老年代區(qū)域,當老年代區(qū)域內存已滿或出現(xiàn)其他情況又會觸發(fā)的的Full GC

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末拇涤,一起剝皮案震驚了整個濱河市捣作,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鹅士,老刑警劉巖券躁,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異掉盅,居然都是意外死亡也拜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門趾痘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慢哈,“玉大人,你說我怎么就攤上這事永票÷鸭” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵侣集,是天一觀的道長键俱。 經(jīng)常有香客問我,道長世分,這世上最難降的妖魔是什么编振? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮罚攀,結果婚禮上党觅,老公的妹妹穿的比我還像新娘雌澄。我一直安慰自己,他們只是感情好杯瞻,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布镐牺。 她就那樣靜靜地躺著,像睡著了一般魁莉。 火紅的嫁衣襯著肌膚如雪睬涧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天旗唁,我揣著相機與錄音畦浓,去河邊找鬼。 笑死检疫,一個胖子當著我的面吹牛讶请,可吹牛的內容都是我干的。 我是一名探鬼主播屎媳,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼夺溢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了烛谊?” 一聲冷哼從身側響起风响,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎丹禀,沒想到半個月后状勤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡双泪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年持搜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攒读。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡朵诫,死狀恐怖辛友,靈堂內的尸體忽然破棺而出薄扁,到底是詐尸還是另有隱情,我是刑警寧澤废累,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布邓梅,位于F島的核電站,受9級特大地震影響邑滨,放射性物質發(fā)生泄漏日缨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一掖看、第九天 我趴在偏房一處隱蔽的房頂上張望匣距。 院中可真熱鬧面哥,春花似錦、人聲如沸毅待。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尸红。三九已至吱涉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間外里,已是汗流浹背怎爵。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盅蝗,地道東北人鳖链。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像墩莫,于是被迫代替她去往敵國和親撒轮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內容