JVM筆記六-堆區知識之對象生命週期和GC的關係

通過上一篇文章的學習,我們對JVM堆區有了初步的認識,接下來,我們繼續展開講解堆區。

對象生命週期和GC的關係。

我們已經知道了,堆區的新生區分成了三個部分:伊甸園區、倖存者0區、倖存者1區。

其中0區也叫from,1區也叫to區。但是這個from和to是固定不變的嗎?NO,NO,NO不是的。當新生區執行一次GC(YGC)後,from和to區會進行交換。交換後,也就是在GC之後,誰空誰是to區。所以,from區和to區的位置和名分不是一成不變的。會發生變化的。

Java堆從GC的角度可以分爲:新生區和老年代。這個是從物理分的。

編輯

新生代和老年代,佔用堆區的比例是:1比2

在新生代中的伊甸園區和倖存者0區、倖存者1區的佔比是:8比1比1

從邏輯來分的話,又有永久代(元空間)。如下圖:

編輯

新生區GC (MinorGC) 的過程:複製->清空->互換

1:複製

eden、Survivor From區 複製到Survivor To區,年齡+1

首先,當Eden區滿的時候會觸發第一次GC,把還存活的對象拷貝到survivorFrom區,當Eden區再次觸發GC的時候,會掃描Eden區和From區域,對這兩個區域進行垃圾回收,經過這次垃圾回收後還存活的對象,則直接複製到To區(如果有對象的年齡已經達到了去往老年代的標準,則這些達到標準的對象將會被複制到老年代區),同時把這些對象的年齡+1

2:清空

清空Eden、survivorFrom區

然後,清空Eden和SuriviorFrom中的對象,也即是複製之後有交換。誰空誰做to區。

3:SurvivorTo和SurvivorFrom互換

最後,Survivor To和Survivor From互換,原來Survivor To成爲下一次GC的Survivor From區,部分對象會在From和To區中複製來複制去的,如此交換15次(由JVM參賽MaxTenuringThreshold決定的,這個參賽默認值就是15),最終如果還是存活的對象,就把這些存活的對象存入到老年代區域。

這個過程可以有個生活中的case.士兵到將軍的過程。士兵上戰場,倖存下來,成班長,下次戰爭來臨的時候,班長帶着新的士兵繼續衝殺,倖存下來,班長升級成排長,以此類推。經歷大大小小戰役十五次之後,升級成了將軍,進入到年老代。

Java7的永久代:

JVM內存管理的模型圖如下:

編輯

Why?

真相:經過研究,不同對象的生命週期是不同的(廢話嘛,不同對象,操作鏈路長短不一樣,當然生命週期不一樣了),98%的對象是臨時對象(臨時對象,就是用完就被回收了)。

實際而言,方法區(Method Area)和堆區一樣,是各個線程共享的內存區域,它用於存儲虛擬機加載的:類信息+普通常量+靜態常量+編譯器編譯後的代碼等等。雖然JVM規範將方法區描述爲堆的一個邏輯部分,但是它卻還有一個別名:N0n-Heap(非堆),目的就是要和堆區分開的(這句話怎麼理解?我們從小教育都知道,臺灣是中國的一部分,但是臺灣還有個別名:中華臺北。其目的就是臺灣想在國際上和中國區分開而已)。

對於HotSpot虛擬機,很多開發者習慣將方法區稱之爲”永久代(Parmanent Gen)”,但嚴格本質上說兩者不同。或者說使用永久代來實現方法區而已,永久代是方法區(相當於是一個接口Interface)的一個實現。JDK1.7的版本中,已經將原本存放永久代的字符串常量池移走了。

三者之間在堆內存中的關係,我們在來看一遍,如下圖:

編輯

永久代:java7之前

永久存儲區是一個常駐內存區域,用於存放JDK自身所攜帶的Class,Interface的元數據,也就是說它存儲的是運行環境必須的類信息,被裝載進此區域的數據是不會被垃圾回收器回收掉的,關閉JVM纔會釋放此區域所佔用的內存。

至此,我們已經把JVM堆區講完了。那麼接下來凱哥(凱哥Java:kaigejava)將接着講解JVM調優命令了。歡迎大家一起繼續學習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章