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

相关文章
相关标签/搜索