JVM垃圾回收(新手推薦)

提到JVM垃圾回收,總覺(jué)得離我們程序員有一定的距離。在JAVA中,那是系統(tǒng)自己干的事,我們關(guān)心那個(gè)干嘛?也就是說(shuō)我們?yōu)槭裁匆獙W(xué)習(xí)這個(gè)東西,大家開(kāi)開(kāi)心心地敲代碼不好嗎?

還真的不好,一方面我覺(jué)得我們可以學(xué)習(xí)下JAVA語(yǔ)言設(shè)計(jì)上的一些思想,另一方面,在我們以后從事一些較為高級(jí)一點(diǎn)的開(kāi)發(fā),尤其是性能調(diào)優(yōu)之類的,知道這些基礎(chǔ)知識(shí)就顯得很必要了。我打算從以下幾個(gè)方面開(kāi)始進(jìn)行簡(jiǎn)單地說(shuō)明。

GC如何知道哪些對(duì)象是垃圾對(duì)象?

GC不可能隨便指派說(shuō)哪個(gè)對(duì)象是垃圾,要有一定的依據(jù)。常用的標(biāo)記垃圾的算法有兩個(gè):

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

引用計(jì)數(shù)算法,就是每個(gè)對(duì)象有一個(gè)引用計(jì)數(shù)器,當(dāng)該對(duì)象被引用的時(shí)候計(jì)數(shù)器加1,當(dāng)引用失效的時(shí)候,計(jì)數(shù)器減1。

那么這么做有什么缺點(diǎn)嗎?

那就是當(dāng)兩個(gè)對(duì)象相互引用的時(shí)候,這兩個(gè)對(duì)象都會(huì)無(wú)法釋放。

根搜索算法

從根對(duì)象開(kāi)始,所有能被觸及的對(duì)象都可以認(rèn)為是“存活的”對(duì)象,換句話說(shuō),就是“仍然使用的”對(duì)象。不能被觸及的對(duì)象,就會(huì)被認(rèn)為是垃圾,需要回收。

根搜索算法(圖片來(lái)自于網(wǎng)絡(luò))
根搜索算法(圖片來(lái)自于網(wǎng)絡(luò))

那么什么對(duì)象可作為GC Roots呢?

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

什么是虛擬機(jī)棧?

虛擬機(jī)棧為Java方法服務(wù)。說(shuō)的簡(jiǎn)單點(diǎn),就是我們平時(shí)所寫的Java方法,沒(méi)調(diào)用一個(gè)Java方法,就是入棧的過(guò)程,退出方法就是出棧的過(guò)程。每個(gè)Java方法對(duì)應(yīng)于虛擬機(jī)棧中的一個(gè)棧幀。

什么是本地方法棧?

本地方法棧為native方法服務(wù)。

方法區(qū)是什么呢?

方法區(qū)與Java堆一樣,是各個(gè)線程共享的內(nèi)存區(qū)域,它用于存儲(chǔ)已被虛擬機(jī)加載的類信息,常量,靜態(tài)變量,即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。可以看做堆的一個(gè)邏輯部分。

常用的垃圾回收算法有哪些?

看下圖,整幢大樓燈火通明,其中不排除一些辦公室沒(méi)人但還是燈亮著的情況,為了節(jié)約資源,我們需要關(guān)掉那些辦公室沒(méi)人的燈。那么怎么辦呢?

內(nèi)存啊
內(nèi)存啊

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

我從頂樓開(kāi)始到一樓,一塊一塊辦公區(qū)域看,對(duì)沒(méi)人的區(qū)域進(jìn)行關(guān)燈。將整個(gè)大樓看成內(nèi)存,燈亮著的區(qū)域表示有對(duì)象存在,燈滅著的表示空閑區(qū)域。我們一塊一塊區(qū)域檢查的這個(gè)過(guò)程就是標(biāo)記的過(guò)程,關(guān)燈的操作就是清除的過(guò)程。這就是標(biāo)記——清除算法。

標(biāo)記——清除算法(圖片來(lái)自于網(wǎng)絡(luò))
標(biāo)記——清除算法(圖片來(lái)自于網(wǎng)絡(luò))

弊端:

  1. 那就是費(fèi)時(shí)費(fèi)力,效率太低。
  2. 不連續(xù),不美觀(內(nèi)存碎片嚴(yán)重)。

復(fù)制回收算法

老板說(shuō)了,浪費(fèi)太嚴(yán)重了,到了晚上,我們對(duì)需要加班的同事進(jìn)行統(tǒng)一安排。假設(shè)大樓共10層,只能使用15層或者610層(畢竟晚上加班的人不多)。比如現(xiàn)在使用的就是15樓,到了晚上要用燈了,需要加班的同事自己去610樓找位置,保安一聽(tīng)樂(lè)了,再也不用一塊一塊區(qū)域關(guān)燈了,有需要的人都去610樓了,剩下的即便是燈亮著的辦公區(qū)域那也是沒(méi)人,讓我分別去15樓拉個(gè)總閘先(回收的過(guò)程)。

復(fù)制回收算法(圖片來(lái)自于網(wǎng)絡(luò))
復(fù)制回收算法(圖片來(lái)自于網(wǎng)絡(luò))

可以看到,在任意時(shí)刻只用到了內(nèi)存的一半。

弊端:

  1. 有需要的同事搬到6~10樓的過(guò)程,太麻煩。特別是需要加班的同事比較多的時(shí)候。(需要對(duì)有用的對(duì)象進(jìn)行復(fù)制)。
  2. 整棟大樓只能用一半,哎(內(nèi)存使用率降低)。

優(yōu)點(diǎn):

從外面看,我知道哪些地方有人,哪些地方?jīng)]人,方便了管理(內(nèi)存無(wú)碎片)。

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

下班后,保安大哥將空的辦公區(qū)域依次統(tǒng)計(jì)出來(lái)(標(biāo)記的過(guò)程),需要加班的同事按照統(tǒng)計(jì)結(jié)果,依次搬到空閑的辦公區(qū)域。保安大哥知道,我只需要找到最后一個(gè)有人的區(qū)域,那么這塊區(qū)域之后肯定不會(huì)有人了,不用挨個(gè)檢查了,去拉后面的閘。

標(biāo)記——整理算法(圖片來(lái)自于網(wǎng)絡(luò))
標(biāo)記——整理算法(圖片來(lái)自于網(wǎng)絡(luò))

優(yōu)點(diǎn):

  1. 內(nèi)存無(wú)碎片。
  2. 同時(shí)避免了當(dāng)有用對(duì)象比較多的時(shí)候,復(fù)制回收算法的麻煩。

分代回收算法

JVM劃分
JVM劃分

新生代:

剛創(chuàng)建的對(duì)象都在新生代,新生代采用復(fù)制回收算法。新生代分為三個(gè)區(qū),一個(gè)Eden區(qū),一般兩個(gè)Survivor區(qū)。大部分對(duì)象在Eden區(qū)生成,當(dāng)Eden區(qū)域滿時(shí),將還存活的對(duì)象復(fù)制到其中一個(gè)Survivor區(qū)域,當(dāng)這個(gè)Survivor區(qū)域滿時(shí),將其中還存活的對(duì)象復(fù)制到第二個(gè)Survivor區(qū)域。那么當(dāng)?shù)诙€(gè)Survivor區(qū)域滿時(shí)該怎么辦呢?那就是將第二個(gè)Survivor區(qū)域中由第一個(gè)Survivor區(qū)域復(fù)制過(guò)來(lái)的對(duì)象,復(fù)制到“老年代”中。

這個(gè)過(guò)程是有點(diǎn)繞,但是可以想象成面試過(guò)程中層層選拔的過(guò)程,能力越強(qiáng)的可以想象成生命周期越長(zhǎng)的對(duì)象。

老年代:

這個(gè)區(qū)域中的對(duì)象都是在新生代中經(jīng)歷了層層回收后仍然存活的對(duì)象,這個(gè)區(qū)域采用標(biāo)記整理的算法進(jìn)行垃圾回收。

持久代:

持久代中用于存放一些靜態(tài)文件,static常亮,常量池等。這塊區(qū)域?qū)厥諞](méi)有顯著影響。

什么時(shí)候會(huì)進(jìn)行垃圾回收?

GC有兩種類型:Minor GC和Full GC。

Minor GC

當(dāng)新對(duì)象生成,并且在Eden申請(qǐng)空間失敗時(shí),就會(huì)觸發(fā)Minor GC,對(duì)Eden區(qū)域進(jìn)行GC,清理非存活對(duì)象。

Full GC

對(duì)整個(gè)堆進(jìn)行整理,所以比Minor要慢,所以盡可能地減少Full GC的次數(shù)。在對(duì)JVM調(diào)優(yōu)的過(guò)程中,很大一部分工作就是對(duì)于Full GC的調(diào)節(jié)。有如下原因可能導(dǎo)致Full GC:

  1. 老年代被寫滿;
  2. 持久代被寫滿;
  3. System.gc()被顯式調(diào)用。

參考資料:《深入理解Java虛擬機(jī):JVM高級(jí)特性與最佳實(shí)踐(第二版)》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡(jiǎn)欲明心閱讀 90,341評(píng)論 17 311
  • 作者:一字馬胡 轉(zhuǎn)載標(biāo)志 【2017-11-12】 更新日志 日期更新內(nèi)容備注 2017-11-12新建文章初版 ...
    beneke閱讀 2,322評(píng)論 0 7
  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前,它的class會(huì)被類裝載器裝入方法區(qū)(Permanent區(qū)),執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,822評(píng)論 0 7
  • 1.一些概念 1.1.數(shù)據(jù)類型 Java虛擬機(jī)中,數(shù)據(jù)類型可以分為兩類:基本類型和引用類型?;绢愋偷淖兞勘4嬖?..
    落落落落大大方方閱讀 4,813評(píng)論 4 86
  • 原文閱讀 前言 這段時(shí)間懈怠了,罪過(guò)! 最近看到有同事也開(kāi)始用上了微信公眾號(hào)寫博客了,挺好的~給他們點(diǎn)贊,這博客我...
    碼農(nóng)戲碼閱讀 6,144評(píng)論 2 31

友情鏈接更多精彩內(nèi)容