1. 程式人生 > 程式設計 >Java物件不使用時賦值null的意義詳解

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日誌列印

Java物件不使用時賦值null的意義詳解

執行上面的程式碼,載圖gc日誌

Java物件不使用時賦值null的意義詳解

現在我們修改上面的測試程式碼,將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日誌

Java物件不使用時賦值null的意義詳解

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

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

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

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

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

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

使用javap -v TestDemo1.class

Java物件不使用時賦值null的意義詳解

可以看到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();
  }
}

Java物件不使用時賦值null的意義詳解

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

而且這段程式碼與placeHolder = null的gc日誌完全一樣。那麼應該可以說明,我們宣告的這個String name = "admin" 斷開了棧中placeHolder與堆中例項之間關係。

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

總結:程式碼離開變數作用域時,並不會自動切斷其與堆的聯絡。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。