java中將對象引用設置為null對於GC有沒有幫助


     相信,網上很多java性能優化的帖子里都會有這么一條: 盡量把不使用的對象顯式得置為null.這樣有助於內存回收

     可以明確的說,這個觀點是基本錯誤的.sun jdk遠比我們想象中的機智.完全能判斷出對象是否已經no ref..但是,我上面用的詞是"基本".也就是說,有例外的情況.這里先把這個例外情況給提出來,后續我會一點點解釋.這個例外的情況是, 方法前面中有定義大的對象,然后又跟着非常耗時的操作,且沒有觸發JIT編譯..總結這句話,就是: 除非在一個方法中,定義了一個非常大的對象,並且在后面又跟着一段非常耗時的操作.並且,該方法沒有滿足JIT編譯條件,否則顯式得設置 obj = null是完全沒有必要的

 上面這句話有點繞,但是,上面說的每一個條件都是有意義的.這些條件分別是

1 同一個方法中
2 定義了一個大對象(小對象沒有意義)
3 之后跟着一個非常耗時的操作.
4 沒有滿足JIT編譯條件

 

 上面4個條件缺一不可,把obj顯式設置成null才是有意義的. 下面我會一一解釋上面的這些條件

同一個方法中

 這個條件是最容易理解的,如果大對象定義在其他方法中,那么是不需要設置成Null的,

 1 public class Test
 2 {
 3  
 4      public static void main(String[] args){
 5      
 6          foo();
 7          
 8          System.gc();
 9      }
10     
11      public static void foo(){
12          byte[] placeholder = new byte[64*1024*1024];
13     }
14 }

 

 對應的輸出如下,可以看到64M的內存已經被回收

D:\>java -verbose:gc Test
[GC 66798K->66120K(120960K), 0.0012225 secs]
[Full GC 66120K->481K(120960K), 0.0059647 secs]

 其實很好理解,placeholder是foo方法的局部變量,在main方法中調用的時候,其實foo方法對應的棧幀已經結束.那么placeholder指向的大對象自然被gc的時候回收了.

 

定義了一個大對象

這句話的意思也很好理解.只有定義的是大的對象,我們才需要關心他盡快被回收.如果你只是定義了一個 Integer i = new Integer(1); 后續手動設置成null讓gc回收是沒有任何意義的.

 

后面跟着一個非常耗時的操作

這里理解是:后面的這個耗時的可能超過了一個GC的周期.例如

1 public static void main(String[] args) throws Exception{
2          byte[] placeholder = new byte[64*1024*1024];
3          Thread.sleep(3000l);
4          // dosomething
5 }

 

 在線程sleep的三秒內,可能jvm已經進行了好幾次ygc.但是由於placeholder一直持有這個大對象,所以造成這個64M的大對象一直無法被回收,甚至有可能造成了滿足進入old 區的條件.這個時候,在sleep之前,顯式得把placeholder設置成Null是有意義的. 但是,如果沒有這個耗時的操作,main方法可以非常快速的執行結束,方法返回,同時也會銷毀對應的棧幀.那么就是回到第一個條件,方法已經執行結束,在下一次gc的時候,自然就會把對應的"垃圾"給回收掉.

 

沒有滿足JIT編譯條件

  jit編譯的觸發條件,這里就不多闡述了.對應的測試代碼和前面一樣

1 public class Test
2 {
3     public static void main(String[] args) throws Exception{
4         byte[] placeholder = new byte[64*1024*1024];
5         placeholder = null;
6         //do some  time-consuming operation
7         System.gc();
8     }
9 }

 

 在解釋執行中,我們認為placeholder = null;是有助於對這個大對象的回收的.在JIT編譯下,JIT編譯器進行控制流和數據流分析后,生成的OopMap就提供比較精確的信息,不需要通過”=null”來告知對象使命已經完成.退一步說,這時即使有”=null”操作,也會被優化掉,生成出來的本地代碼與沒有”=null”操作的版本是一模一樣的.

 

轉自http://chenjingbo.iteye.com/blog/1980908


免責聲明!

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



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