004-JVM-Java中使用的標記階段的演算法:可達性分析演算法中GC Roots有哪些

前路無畏發表於2020-12-17

上一篇:003-JVM-標記階段的演算法:怎麼確定垃圾 https://blog.csdn.net/fsjwin/article/details/111322134

gc roots有哪些呢?這個是面試題,也要背下來,如果不想進大廠的話,可以不背。

1. 常規gc roots

在這裡插入圖片描述

    1. JVM stack
      虛擬機器棧中引用的物件
      比如: 各個執行緒被呼叫的方法中使用到的引數、區域性變數等
    1. nativ method stack
      JNI( 通常說的本地方法) 引用的物件
    1. runtime constant pool
      執行時常量池
    1. static references in method area
      (堆jdk8)中類靜態屬性引用的物件
      比如: Java 類的引用型別靜態變數
      (堆jdk8) 中常量引用的物件
      比如: 字串常量池(String Table ) 裡的引用
    1. Clazz
      Java 虛擬機器內部的引用。
      基本資料型別對應的Class物件, 一些常駐的異常物件( 如:NullPointerException 、OutOfMemoryError) , 系統類載入器
    1. 所有被同步鎖synchronized持有的物件
      在這裡插入圖片描述
      在這裡插入圖片描述

除了這些固定的GC Roots集合以外, 根據使用者所選用的垃圾收集器以及當前回收的記憶體區域不同, 還可以有其他物件“ 臨時性” 地加入, 共同構成完整GC Roots 集合。比如: 分代收集和區域性回收( Partial GC)
如果只針對Java 堆中的某一塊區域進行垃圾回收( 比如: 典型的只針對新生代) , 必須考慮到記憶體區域是虛擬機器自己的實現細節, 更不是孤立封閉的, 這個區域的物件完全有可能被其他區域的物件所引用,這時候就需要一併將關聯的區域物件也加入GC Roots集合中去考慮, 才能保證可達性分析的準確性。
區域性回收:意思如果分代回收的時候,比如對年輕代進行回收,那麼在老年代中的變數(其指向了年輕代。),也需要放入Roots Set中。否則就會出現誤傷!
小技巧:由於Root採用棧方式存放變數和指標, 所以如果一個指標, 它儲存了堆記憶體裡面的物件, 但是自己又不存放在堆記憶體裡面, 那它就是一個Root。

2. 臨時 gc roots

除了這些固定的GC Roots集合以外, 根據使用者所選用的垃圾收集器以及當前回收的記憶體區域不同, 還可以有其他物件“ 臨時性” 地加入, 共同構成完整GC Roots 集合。比如: 分代收集和區域性回收( Partial GC)

  1. 如果只針對Java 堆中的某一塊區域進行垃圾回收( 比如: 典型的只針對新生代) , 必須考慮到記憶體區域是虛擬機器自己的實現細節, 更不是孤立封閉的, 這個區域的物件完全有可能被其他區域的物件所引用,這時候就需要一併將關聯的區域物件也加入GC Roots集合中去考慮, 才能保證可達性分析的準確性。
  2. 區域性回收:意思如果分代回收的時候,比如對年輕代進行回收,那麼在老年代中的變數(其指向了年輕代。),也需要放入Roots Set中。否則就會出現誤傷!

小技巧:由於Root採用棧方式存放變數和指標, 所以如果一個指標, 它儲存了堆記憶體裡面的物件, 但是自己又不存放在堆記憶體裡面, 那它就是一個Root。(此說法不嚴謹:比如上面提到的 “ 臨時性” 地加入的;jdk8中的StringTable、Static變數等,均在堆中。
但是可以作為一般的評判標準)

3. 總結

  1. 常規的6中需要在roots set中
  2. 特殊的兩種在roots set 中。

相關文章