JVM GC

什麼樣的對象會被GC?

超出作用域或者引用計數爲空的對象,從gc root開始搜索找不到的對象,並且經歷過一次標記、清理後,仍然沒有復活的對象。

解釋:
對象被引用一次,引用計數+1。但是若出現兩個對象互相引用,沒有其他對象引用他們,那麼他們會造成資源泄露。所以只適合一些簡單的引用場景。

GC roots”,或者說tracing GC的“根集合”,就是一組必須活躍的引用,不是對象。

例如說,這些引用可能包括:

  • 所有Java線程當前活躍的棧幀裏指向GC堆裏的對象的引用;換句話說,當前所有正在被調用的方法的引用類型的參數/局部變量/臨時值。
  • VM的一些靜態數據結構裏指向GC堆裏的對象的引用,例如說HotSpot VM裏的Universe裏有很多這樣的引用。 JNI
    handles,包括global handles和local handles
  • (看情況)所有當前被加載的Java類
  • (看情況)Java類的引用類型靜態變量
  • (看情況)Java類的運行時常量池裏的引用類型常量(String或Class類型)
  • (看情況)String常量池(StringTable)裏的引用

Tracing GC的根本思路就是:給定一個集合的引用作爲根出發,通過引用關係遍歷對象圖,能被遍歷到的(可到達的)對象就被判定爲存活,其餘對象(也就是沒有被遍歷到的)就自然被判定爲死亡。注意再注意:tracing GC的本質是通過找出所有活對象來把其餘空間認定爲“無用”,而不是找出所有死掉的對象並回收它們佔用的空間。
GC roots這組引用是tracing GC的起點。要實現語義正確的tracing GC,就必須要能完整枚舉出所有的GC roots,否則就可能會漏掃描應該存活的對象,導致GC錯誤回收了這些被漏掃的活對象。

這就像任何遞歸定義的關係一樣,如果只定義了遞推項而不定義初始項的話,關係就無法成立——無從開始;而如果初始項定義漏了內容的話,遞推出去也會漏內容。

那麼分代式GC對GC roots的定義有什麼影響呢?
答案是:分代式GC是一種部分收集(partial collection)的做法。在執行部分收集時,從GC堆的非收集部分指向收集部分的引用,也必須作爲GC roots的一部分。
具體到分兩代的分代式GC來說,如果第0代叫做young gen,第1代叫做old gen,那麼如果有minor GC / young GC只收集young gen裏的垃圾,則young gen屬於“收集部分”,而old gen屬於“非收集部分”,那麼從old gen指向young gen的引用就必須作爲minor GC / young GC的GC roots的一部分。
繼續具體到HotSpot VM裏的分兩代式GC來說,除了old gen到young gen的引用之外,有些帶有弱引用語義的結構,例如說記錄所有當前被加載的類的SystemDictionary、記錄字符串常量引用的StringTable等,在young GC時必須要作爲strong GC roots,而在收集整堆的full GC時則不會被看作strong GC roots。

換句話說,young GC比full GC的GC roots還要更大一些。

什麼時候進行GC?

1、直接調用System.gc()進行GC

2、老年代空間不足時觸發full GC。
老年代只有在新生代對象轉爲大對象、大數組時纔會出現空間不足的現象,當執行Full GC後空間依然不足時,則會拋出java.lang.OutOfMemoryError: Java heap space 。爲避免以上兩種狀況引起的FullGC,調優時應儘量做到讓對象在Minor GC階段被回收、讓對象在新生代多存活一段時間及不要創建過大的對象及數組。

3、Permanet Generation(又稱方法區、持久代)空間滿
Permanet Generation中存放的爲一些class的信息等,當系統中要加載的類、反射的類和調用的方法較多時,Permanet Generation可能會被佔滿,在未配置爲採用CMS GC的情況下會執行Full GC。如果經過Full GC仍然回收不了,那麼JVM會拋出如下錯誤信息:java.lang.OutOfMemoryError: PermGen space
爲避免Perm Gen佔滿造成Full GC現象,可採用的方法爲增大Perm Gen空間或轉爲使用CMS GC。

4、統計得到的Minor GC晉升到老年代的平均大小大於老年代的剩餘空間
這是一個較爲複雜的觸發情況,Hotspot爲了避免由於新生代對象晉升到舊生代導致舊生代空間不足的現象,在進行Minor GC時,做了一個判斷,如果之前統計所得到的Minor GC晉升到舊生代的平均大小大於舊生代的剩餘空間,那麼就直接觸發Full GC。

例如程序第一次觸發MinorGC後,有6MB的對象晉升到舊生代,那麼當下一次Minor GC發生時,首先檢查舊生代的剩餘空間是否大於6MB,如果小於6MB,則執行Full GC。

當新生代採用PSGC時,方式稍有不同,PS GC是在Minor GC後也會檢查,例如上面的例子中第一次Minor GC後,PS GC會檢查此時舊生代的剩餘空間是否大於6MB,如小於,則觸發對舊生代的回收。

程序員不能具體控制時間,系統在不可預測的時間調用System.gc()函數的時候;當然可以通過調優,用NewRatio控制newObject和oldObject的比例,用MaxTenuringThreshold 控制進入oldObject的次數,使得oldObject 存儲空間延遲達到full gc,從而使得計時器引發gc時間延遲OOM的時間延遲,以延長對象生存期

eden滿了minor gc,升到老年代的對象大於老年代剩餘空間full
gc,或者小於時被HandlePromotionFailure參數強制full
gc;gc與非gc時間耗時超過了GCTimeRatio的限制引發OOM,調優諸如通過NewRatio控制新生代老年代比例,通過
MaxTenuringThreshold控制進入老年前生存次數等

GC 時做了什麼?

1、刪除不使用的對象,回收內存空間
2、停止其他線程執行、運行finalize。
3、新生代整理內存時,進行復制整理。使用了兩個內存空間from survivor、to survivor。
4、老年代進行標記清理、標記清理後進行壓縮,清楚碎片。

GC的策略有哪些?優劣勢?適用於什麼場景?

Heap劃分爲兩大類New Generation(新生代),Old Generation(老年代)。Minor GC是針對New Generation的,而Full GC是則是對新生代和老年代一起做GC, 所以Full GC的開銷會非常大,要淨量避免。
1、New Generation GC策略:Minor GC

 Serial GC。採用單線程方式,用Copying算法。New Generation會再次被劃分成Eden Space和S0、S1,Copying算法所需要的額外內存空間,S0和S1又稱爲From Space和To Space。
 Parallel Scavenge。將內存空間分段來使用多線程,Copying算法。
 ParNew,比Parallel Scavenge多做了與Old Generation使用CMS GC一起發生時的特殊處理。

2、 Old Generation的GC策略

 Serial GC。採用單線程方式,使用Mark-Sweep和Mark-Compact gc算法。
 Parallel Mark-Sweep、Parallel Mark-Compact。同樣也是把Old Generation空間進行劃分成regions,只是粒度更細了。
 CMS(Concurrent Mark-Sweep) GC。我承認這個GC我真的沒怎麼看懂,目的是爲了實現併發,結果就造成具體實現太麻煩了。有興趣的朋友去看書吧,文末我說了是哪本書。這裏有個地方可以說一下,就是算法使用的還是Mark-Sweep,對於內存碎片的問題,CMS提供了一個內存碎片的整理功能,會在執行幾次Full GC以後執行一次。

GC算法

1、引用計數法
一個對象,每被引用一次計數+1,只要對象不在任何地方被引用,那麼他將被回收。但是存在一個問題,兩個對象互相引用,但是都不被第三個對象引用,則會造成資源泄露。故該算法只能用於簡單的引用場景。
2、跟蹤收集法
把系統的整個引用想象成一個允許有環路的樹形結構,但根節點只有一個,然後從根節點出發查看對象是否可達。但是這個需要程序暫停,來保證一次掃描的現場不變。
3、複製法Copying
需要兩塊內存空間,把掃描的可達對象複製到另一個空間,然後把原空間全部清除。適用於存活對象較少的情況。
4、標記清除法Mark-Sweep
把掃描到的可達對象都標記起來,然後把未標記的對象清除。該清除法會有內存碎片。適用於存活對象較多的情況。
5、標記清除壓縮法Mark-Compact
把掃描到的可達對象都標記起來,然後把未標記的對象清除,然後進行壓縮,讓內存連續起來清除碎片。

摘至:
http://blog.csdn.net/cy609329119/article/details/51771953
http://blog.csdn.net/u014421556/article/details/52396706
https://www.zhihu.com/question/53613423/answer/135743258

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