Java面試基礎知識複習—2-GC

2 GC

Java垃圾回收機制,GC,ZGC等機制
常見的調優參數

命令 說明
-XX:SurvivorRatio Eden和Survivor的比值,默認8:1
-XX:NewRatio 老年代的和年輕代內存大小的比例
-XX:MaxTenuringThreshold 對象從年輕代晉升到老年代經過GC次數最大的閾值
-XX:+PretenuerSizeThreshold 新生成的對象可直接變爲老年代的閾值

2.1 垃圾回收之標記算法

(1)對象被判定爲垃圾的標準
沒有被其他對象引用的就是"垃圾"
(2)判定對象是否爲垃圾的算法有兩種:引用計數算法可達性分析算法

引用計數算法:

  • 通過判斷對象的引用數量來決定對象是否可以被回收; 每個對象實例都有一個引用計數器,被引用則+1,完成引用-1; 任何引用計數器爲0的對象實例,都可以被當作垃圾收集
  • 優點:執行效率高,程序執行受影響較小
  • 缺點:無法檢測出循環引用的情況,導致內存泄漏(例如,兩個對象互相引用)

可達性分析算法:

  • 通過判斷對象的引用鏈是否可達來決定對象是否可以被回收; 可以想象這個程序中所有的引用都是從一個GC Root出發,鏈接起來的引用圖,如果在圖中,說明對象還在被引用,如果沒有被引用則可以判定爲垃圾
  • 可以作爲GC Root的對象:
  • 虛擬機棧中引用的對象(棧幀中的本地變量表)
  • 方法區中的常量引用對象
  • 方法區中的類靜態屬性引用對象
  • 本地方法棧中JNI(Native方法)的引用對象
  • 活躍線程的引用對象

2.2 談談你瞭解的垃圾回收算法

(1) 標記-清除算法(Mark and Sweep)

  • 標記:從根集合進行掃描,對存活的對象進行標記; 清除:對堆內存從頭到尾進行線性遍歷,回收不可達對象內存
  • 產生的後果:容易導致內存碎片化

(2)複製算法(Copying)

  • 將一塊可用的內存按比例或者容量分爲對象面空閒面,對象在對象面上創建,存活的對象被從對象面複製到空閒面,將對象面所有內存清除
  • 優點:解決碎片化問題,順序分配內存,簡單高效,適用於對象存活率低的場景(尤其適用於年輕代中)

(3)標記-整理算法(Compacting)

  • 標記:從根集合進行掃描,對存活的對象進行標記; 清除:移動所有存活的對象,且按照內存地址依次排列,然後將末端內存地址以後的內存全部回收.
  • 優點:解決了標記-清除算法中產生的碎片化問題,避免了內存的不連續;不用設置兩塊內存互換;適用於存活率高的場景(如老年代中)
  • 缺點:成本更高;

(4)分代收集算法(Generational Collector)

  • 可以理解爲是垃圾回收算法的組合拳; 其按照對象生命週期的不同劃分在不同堆中,對不同的堆採用不同的垃圾回收算法
  • 目的: 爲了提高JVM垃圾回收效率
  • 分帶收集算法中GC的分類: MinorGC,Full GC

2.3 分代收集算法的應用

在這裏插入圖片描述
(1)在年輕代中使用複製算法
年輕代:存放那些生命週期短的對象,其分爲Eden區和兩個Survivor區(分別叫做from,to),這三個區的大小比例爲8:1:1.

創建新的對象是在Eden區中,在進行GC時,使用複製算法將Eden中存活對象和from區中存活對象複製到to區中,年齡+1,清空Eden區和from區.此時,from區變爲了to區,to區變爲from區,下一次觸發GC時,依舊是使用複製算法將Eden中存活對象和from區中存活對象複製到to區中,年齡+1,清空Eden區和from區.

當某個存活對象的年齡達到某個值(比如15時,其可以通過-XX:MaxTenuringThreshold設置),就會被移動到老年代中.

(2)對象如何晉升到老年代

  • ①首先在經歷一定的Minor次數依舊存活的對象(也就是年齡達到要求的)
  • ②Survivor區中存放不下的對象
  • ③新生成的大對象(-XX:+PretenuerSizeThreshold)

(3)在老年代中使用標記-清除算法標記-整理算法
老年代:存放生命週期較長的對象

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