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

     相信,網上不少java性能優化的帖子裏都會有這麼一條: 儘可能把不使用的對象顯式得置爲null.這樣有助於內存回收java

     能夠明確的說,這個觀點是基本錯誤的.sun jdk遠比咱們想象中的機智.徹底能判斷出對象是否已經no ref..可是,我上面用的詞是"基本".也就是說,有例外的狀況.這裏先把這個例外狀況給提出來,後續我會一點點解釋.這個例外的狀況是, 方法前面中有定義大的對象,而後又跟着很是耗時的操做,且沒有觸發JIT編譯..總結這句話,就是: 除非在一個方法中,定義了一個很是大的對象,而且在後面又跟着一段很是耗時的操做.而且,該方法沒有知足JIT編譯條件,不然顯式得設置 obj = null是徹底沒有必要的性能優化

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

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的時候回收了.spa

 

定義了一個大對象

這句話的意思也很好理解.只有定義的是大的對象,咱們才須要關心他儘快被回收.若是你只是定義了一個 String str = "abc"; 後續手動設置成null讓gc回收是沒有任何意義的.線程

 

後面跟着一個很是耗時的操做

這裏理解是:後面的這個耗時的可能超過了一個GC的週期.例如code

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

相關文章
相關標籤/搜索