總結Minor GC、Full GC觸發條件

向著光亮的地方前行發表於2020-12-18

GC,即就是Java垃圾回收機制。目前主流的JVM(HotSpot)採用的是分代收集演算法。與C++不同的是,Java採用的是類似於樹形結構的可達性分析法來判斷物件是否還存在引用。即:從gcroot開始,把所有可以搜尋得到的物件標記為存活物件。

GC機制

要準確理解Java的垃圾回收機制,就要從:“什麼時候”,“對什麼東西”,“做了什麼”三個方面來具體分析。

第一:“什麼時候”即就是GC觸發的條件。GC觸發的條件有兩種。(1)程式呼叫System.gc時可以觸發(會建議JVM進行垃圾回收,不代表一定會進行GC);(2)系統自身來決定GC觸發的時機。

系統判斷GC觸發的依據:根據Eden區和From Space區的記憶體大小來決定。當記憶體大小不足時,則會啟動GC執行緒並停止應用執行緒。

第二:“對什麼東西”籠統的認為是Java物件並沒有錯。但是準確來講,GC操作的物件分為:通過可達性分析法無法搜尋到的物件和可以搜尋到的物件。對於搜尋不到的方法進行標記。

第三:“做了什麼”最淺顯的理解為釋放物件。但是從GC的底層機制可以看出,對於可以搜尋到的物件進行復制操作,對於搜尋不到的物件,呼叫finalize()方法進行釋放。

具體過程:當GC執行緒啟動時,會通過可達性分析法把Eden區和From Space區的存活物件複製到To Space區,然後把Eden Space和From Space區的物件釋放掉。當GC輪訓掃描To Space區一定次數後,把依然存活的物件複製到老年代,然後釋放To Space區的物件。

對於用可達性分析法搜尋不到的物件,GC並不一定會回收該物件。要完全回收一個物件,至少需要經過兩次標記的過程。

第一次標記:對於一個沒有其他引用的物件,篩選該物件是否有必要執行finalize()方法,如果沒有執行必要,則意味可直接回收。(篩選依據:是否複寫或執行過finalize()方法;因為finalize方法只能被執行一次)。

第二次標記:如果被篩選判定位有必要執行,則會放入FQueue佇列,並自動建立一個低優先順序的finalize執行緒來執行釋放操作。如果在一個物件釋放前被其他物件引用,則該物件會被移除FQueue佇列。

GC過程中用到的回收演算法:

通過上面的GC過程不難看出,Java堆中的年輕代和老年代採用了不同的回收演算法。年輕代採用了複製法;而老年代採用了標記-整理法

具體各種回收演算法的詳解參考:http://www.cnblogs.com/dolphin0520/p/3783345.html

JVM記憶體空間圖解

 

程式計數器:執行緒私有。是一塊較小的記憶體,是當前執行緒所執行的位元組碼的行號指示器。是Java虛擬機器規範中唯一沒有規定OOM(OutOfMemoryError)的區域。

Java棧:執行緒私有。生命週期和執行緒相同。是Java方法執行的記憶體模型。執行每個方法都會建立一個棧幀,用於儲存區域性變數和運算元(物件引用)。區域性變數所需要的記憶體空間大小在編譯期間完成分配。所以棧幀的大小不會改變。存在兩種異常情況:若執行緒請求深度大於棧的深度,拋StackOverflowError。若棧在動態擴充套件時無法請求足夠記憶體,拋OOM。

Java堆:所有執行緒共享。虛擬機器啟動時建立。存放物件實力和陣列。所佔記憶體最大。分為新生代(Young區),老年代(Old區)。新生代分Eden區,Survivor區。Survivor區又分為From space區和To Space區。Eden區和Survivor區的記憶體比為8:1。 當擴充套件記憶體大於可用記憶體,拋OOM。

方法區:所有執行緒共享。用於儲存已被虛擬機器載入的類資訊、常量、靜態變數等資料。又稱為非堆(Non – Heap)。方法區又稱“永久代”。GC很少在這個區域進行,但不代表不會回收。這個區域回收目標主要是針對常量池的回收和對型別的解除安裝。當記憶體申請大於實際可用記憶體,拋OOM。

本地方法棧:執行緒私有。與Java棧類似,但是不是為Java方法(位元組碼)服務,而是為本地非Java方法服務。也會拋StackOverflowError和OOM。

 

 Minor GC ,Full GC 觸發條件

Minor GC觸發條件:當Eden區滿時,觸發Minor GC。

Full GC觸發條件:

(1)呼叫System.gc時,系統建議執行Full GC,但是不必然執行

(2)老年代空間不足

(3)方法去空間不足

(4)通過Minor GC後進入老年代的平均大小大於老年代的可用記憶體

(5)由Eden區、From Space區向To Space區複製時,物件大小大於To Space可用記憶體,則把該物件轉存到老年代,且老年代的可用記憶體小於該物件大小

相關文章