java對象不再使用時賦值null的意義


先看代碼

public class TestDemo1 {
    public static void main(String[] args) {
        if (true) {
            byte[] placeHolder = new byte[64 * 1024 * 1024];
            System.out.println(placeHolder.length / 1024);
        }
        System.gc();
    }
}

 

idea配置gc日志打印

 

運行上面的代碼,載圖gc日志

 

現在我們修改上面的測試代碼,將 placeHolder置為null

 

public class TestDemo1 {
    public static void main(String[] args) {
        if (true) {
            byte[] placeHolder = new byte[64 * 1024 * 1024];
            System.out.println(placeHolder.length / 1024);
            placeHolder = null;
        }
        System.gc();
    }
}

 

再次運行程序,查看gc日志

 

由以上載圖日志可以明顯看到二者差別, 所以不用對象置為null還是很有意義的。

為啥會造成二者的區別呢? 

這還得從jvm認定垃圾的機制:可達性分析說起。

說起這個可達性,首先就得說到根,而“本地變量表”恰恰就可以看成是根。

上面兩段代碼本地變量表是不一樣的。

 

先看第一段代碼,就是 placeHolder沒有置null的“本地變量表 ”

使用javap -v TestDemo1.class

可以看到 placeHolder還在本地變量表中,而且它占用slot槽1號位置, 所以jvm認為它還是活着的。

 

然后,我們再看placeHolder = null 這段代碼的"本地變量表"的情況,其實它與上面一樣,看不出啥差別。

 

但是如果我們在placeHolder后面再聲明一個變量

public class TestDemo1 {
    public static void main(String[] args) {
        if (true) {
            byte[] placeHolder = new byte[64 * 1024 * 1024];
            System.out.println(placeHolder.length / 1024);
        }
        String name = "admin";
        System.gc();
    }
}

 

可以看到name 這個變量名將 slot槽1號位置占用了,是否可以說明placeHolder沒啥用了呢

而且這段代碼與 placeHolder = null 的gc日志完全一樣。 那么應該可以說明,我們聲明的這個String name = "admin"  斷開了棧中placeHolder與堆中實例 之間關系。

而placeHolder = null 應該也有這個功能。

 

 

總結: 代碼離開變量作用域時,並不會自動切斷其與堆的聯系。

 


免責聲明!

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



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