1. 程式人生 > >引用設成null對GC有幫助嗎?

引用設成null對GC有幫助嗎?

轉載自:http://www.newsmth.net/nForum/#!article/Java/275101?p=2

經常聽到過這種說法:如果一個物件沒有被RC Roots直接或間接引用,就會被GC. 如果顯示地把它設成null,可以幫助GC。是否真的有用?
public static void main(String[] args)() { 
     byte[] placeholder = new byte[64 * 1024 * 1024]; 
     System.gc(); 
} 
在HotSpot VM、未JIT的前提下,GC日誌為: 
[GC 66846K->65824K(125632K), 0.0032678 secs]  
[Full GC 65824K->65746K(125632K), 0.0064131 secs]  

public static void main(String[] args)() { 
     byte[] placeholder = new byte[64 * 1024 * 1024]; 
     placeholder = null; 
     System.gc(); 
} 
在HotSpot VM、未JIT的前提下,GC日誌為:
[GC 66401K->65778K(125632K), 0.0035471 secs]  
[Full GC 65778K->218K(125632K), 0.0140596 secs]

分析:
       HotSpot解釋執行程式碼時,列舉GC Roots時,OopMap資訊來源於類載入時的分析結果,由於這階段基本沒有對bytecode做過優化,OopMap的資料是比較粗糙的,由變數作用域範圍,或者在說區域性變量表中的存活時間所得出。PS:對OopMap和GC對物件是否可回收的判定,可以參考這篇文章:
http://icyfenix.iteye.com/blog/1166660

      就這個例子來說,可以理解為直到System.gc()執行的那一刻,區域性變量表中還有對placeholder的引用,因此在GC前的”=null”操作,實際是移除掉區域性變量表中的placeholder引用,所以有”=null”的版本成功回收掉64M記憶體。
       那實驗看起來不是證明”=null”某些情況下是有用的嗎?實際上前面說了,”=null”作用僅僅是打斷區域性變量表中的引用。而做到這點並不一定非得placeholder = null,把這句替換成“int a = 1”也能達到效果,反正就把那個坑佔了,不在乎扔進去的是“null”還是“1”。
       最關鍵的是,上面實驗建立在“未JIT的前提下”,在JIT編譯器進行控制流和資料流分析後,生成的OopMap就提供比較精確的資訊,不需要通過”=null”來告知物件使命已經完成。退一步說,這時即使有”=null”操作,也會被優化掉,生成出來的原生代碼與沒有”=null”操作的版本是一模一樣的。對於在意效能的程式碼,必定是執行頻率高,會被JIT的,而不會被JIT的,也不需要在意效率,因此”=null”沒有意義。