JVM GC原理


了解JVM GC原理非常重要,對於系統調優非常有用。如果一個系統頻繁發生FULL GC,那么會造成系統響應卡頓,更嚴重的時候會導致系統崩潰。

JVM的內存空間

JVM的內存空間,從大的層面上來分析包含:新生代空間(Young)和老年代空間(Old)。新生代空間(Young)又被分為2個部分(Eden區域、Survivous區域)和3個板塊(1個Eden區域和2個Survivous區域)

下邊來看下具體每部分都是用來干什么的。

1)Eden(伊甸園)區域:用來存放使用new或者newInstance等方式創建的對象,默認這些對象都是存放在Eden區,除非這個對象太大,或者超出了設定的閾值-XX:PretenureSizeThresold,這樣的對象會被直接分配到Old區域。

2)2個Survivous(幸存)區域:一般稱為S0,S1,理論上他們一樣大。

下邊將會講解它們如何工作的。

第一次GC:

在不斷創建對象的過程中,當Eden區域被占滿,此時會開始做Young GC也叫Minor GC

1)第一次GC時Survivous中S0區和S1區都為空,將其中一個作為To Survivous(用來存儲Eden區域執行GC后不能被回收的對象)。比如:將S0作為To Survivous,則S1為From Survivous。

2)將Eden區域經過GC不能被回收的對象存儲到To Survivous(S0)區域(此時Eden區域的內存會在垃圾回收的過程中全部釋放),但如果To Survivous(S0)被占滿了,Eden中剩下不能被回收對象只能存放到Old區域。

3)將Eden區域空間清空,此時From Survivous區域(S1)也是空的。

4)S0與S1互相切換標簽,S0為From Survivous,S1為To Survivous。

 

第二次GC:

當第二次Eden區域被占滿時,此時開始做GC

1)將Eden和From Survivous(S0)中經過GC未被回收的對象遷移到To Survivous(S1),如果To Survious(S1)區放不下,將剩下的不能回收對象放入Old區域;

2)將Eden區域空間和From Survivous(S0)區域空間清空;

3)S0與S1互相切換標簽,S0為To Survivous,S1為From Survivous。

 

第三次,第四次一次類推,始終保證S0和S1有一個空的,用來存儲臨時對象,用於交換空間的目的。反反復復多次沒有被淘汰的對象,將會被放入Old區域中,默認15次(由參數--XX:MaxTenuringThreshold=15 決定)。

GC中相關問題

問題1:怎么定義活着的對象?

從根引用開始,對象的內部屬性可能也是引用,只要能級聯到的都被認為是活着的對象。

問題2:什么是根?

本地變量引用,操作數棧引用,PC寄存器,本地方法棧引用等這些都是根。

問題3:對象進入Old區域有什么壞處?

Old區域一般稱為老年代,老年代與新生代不一樣。新生代,我們可以認為存活下來的對象很少,而老年代則相反,存活下來的對象很多,所以JVM的堆內存,才是我們通常關注的主戰場,因為這里面活着的對象非常多,所以發生一次FULL GC,來找出來所有存活的對象是非常耗時的,因此,我們應該避免FULL GC的發生。

問題4:S0和S1一般多大,靠什么參數來控制,有什么變化?

一般來說很小,我們大概知道它與Young差不多相差一倍的比例,設置的參數主要有兩個:

-XX:SurvivorRatio=8
-XX:InitialSurvivorRatio=8

第一個參數(-XX:SurvivorRatio)是Eden和Survivous區域比重(注意Survivous一般包含兩個區域S0和S1,這里是一個Survivous的大小)。如果將-XX:SurvivorRatio=8設置為8,則說明Eden區域是一個Survivous區的8倍,換句話說S0或S1空間是整個Young空間的1/10,剩余的8/10由Eden區域來使用。

第二個參數(-XX:InitialSurvivorRatio)是Young/S0的比值,當其設置為8時,表示S0或S1占整個Young空間的1/8(或12.5%)。

問題5:一個對象每次Minor GC時,活着的對象都會在S0和S1區域轉移,講過MInor GC多少次后,會進入Old區域呢?

默認是15次,參數設置

--XX:MaxTenuringThreshold=15

,計數器會在對象的頭部記錄它的交換次數。

問題6:為什么發生FULL GC會帶來很大的危害?

在發生FULL GC的時候,意味着JVM會安全的暫停所有正在執行的線程(Stop The World),來回收內存空間,在這個時間內,所有除了回收垃圾的線程外,其他有關JAVA的程序,代碼都會靜止,反映到系統上,就會出現系統響應大幅度變慢,卡機等狀態。

 

參考:《透視JVM之垃圾回收


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM