您好,登錄后才能下訂單哦!
先看代碼
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應該也有這個功能。
總結:代碼離開變量作用域時,并不會自動切斷其與堆的聯系。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。