GCRoots


JVM面試匯總

JVM垃圾回收的時候如何確定垃圾?是否知道什么是GC Roots

什么是垃圾

簡單來說就是內存中已經不再被使用的空間就是垃圾

如何判斷一個對象是否可以被回收

引用計數法

Java中,引用和對象是有關聯的。如果要操作對象則必須用引用進行。

因此,很顯然一個簡單的辦法就是通過引用計數來判斷一個對象是否可以回收。簡單說,給對象中添加一個引用計數器

每當有一個地方引用它,計數器值加1

每當有一個引用失效,計數器值減1

任何時刻計數器值為零的對象就是不可能再被使用的,那么這個對象就是可回收對象。

那么為什么主流的Java虛擬機里面都沒有選用這個方法呢?其中最主要的原因是它很難解決對象之間相互循環引用的問題。

該算法存在但目前無人用了,解決不了循環引用的問題,了解即可。

枚舉根節點做可達性分析

根搜索路徑算法

為了解決引用計數法的循環引用個問題,Java使用了可達性分析的方法:

所謂 GC Roots 或者說 Tracing Roots的“根集合” 就是一組必須活躍的引用

基本思路就是通過一系列名為 GC Roots的對象作為起始點,從這個被稱為GC Roots的對象開始向下搜索,如果一個對象到GC Roots沒有任何引用鏈相連,則說明此對象不可用。也即給定一個集合的引用作為根出發,通過引用關系遍歷對象圖,能被遍歷到的(可到達的)對象就被判定為存活,沒有被遍歷到的對象就被判定為死亡

必須從GC Roots對象開始,這個類似於linux的 / 也就是根目錄

藍色部分是從GC Roots出發,能夠循環可達

而白色部分,從GC Roots出發,無法到達

一句話理解GC Roots

假設我們現在有三個實體,分別是 人,狗,毛衣

然后他們之間的關系是:人 牽着 狗,狗穿着毛衣,他們之間是強連接的關系

有一天人消失了,只剩下狗狗 和 毛衣,這個時候,把人想象成 GC Roots,因為 人 和 狗之間失去了繩子連接,

那么狗可能被回收,也就是被警察抓起來,被送到流浪狗寄養所

假設狗和人有強連接的時候,狗狗就不會被當成是流浪狗

那些對象可以當做GC Roots

  • 虛擬機棧(棧幀中的局部變量區,也叫做局部變量表)中的引用對象
  • 方法區中的類靜態屬性引用的對象
  • 方法區中常量引用的對象
  • 本地方法棧中的JNI(Native方法)的引用對象

代碼說明


/**
 * 在Java中,可以作為GC Roots的對象有:
 * - 虛擬機棧(棧幀中的局部變量區,也叫做局部變量表)中的引用對象
 * - 方法區中的類靜態屬性引用的對象
 * - 方法區中常量引用的對象
 * - 本地方法棧中的JNI(Native方法)的引用對象
 */
public class GCRootDemo {


    // 方法區中的類靜態屬性引用的對象
    // private static GCRootDemo2 t2;

    // 方法區中的常量引用,GC Roots 也會以這個為起點,進行遍歷
    // private static final GCRootDemo3 t3 = new GCRootDemo3(8);

    public static void m1() {
        // 第一種,虛擬機棧中的引用對象
        GCRootDemo t1 = new GCRootDemo();
        System.gc();
        System.out.println("第一次GC完成");
    }
    public static void main(String[] args) {
        m1();
    }
}


免責聲明!

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



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