相信,网上很多java性能优化的帖子里都会有这么一条: 尽量把不使用的对象显式得置为null.这样有助于内存回收

可以明确的说,这个观点是基本错误的.sun jdk远比我们想象中的机智.完全能判断出对象是否已经no ref..但是,我上面用的词是"基本".也就是说,有例外的情况.这里先把这个例外情况给提出来,后续我会一点点解释.这个例外的情况是, 方法前面中有定义大的对象,然后又跟着非常耗时的操作,且没有触发JIT编译..总结这句话,就是: 除非在一个方法中,定义了一个非常大的对象,并且在后面又跟着一段非常耗时的操作.并且,该方法没有满足JIT编译条件,否则显式得设置 obj = null是完全没有必要的

上面这句话有点绕,但是,上面说的每一个条件都是有意义的.这些条件分别是

 同一个方法中
定义了一个大对象(小对象没有意义)
之后跟着一个非常耗时的操作.
没有满足JIT编译条件

上面4个条件缺一不可,把obj显式设置成null才是有意义的. 下面我会一一解释上面的这些条件

同一个方法中

这个条件是最容易理解的,如果大对象定义在其他方法中,那么是不需要设置成Null的,

 public class Test
{ public static void main(String[] args){ foo(); System.gc();
} public static void foo(){
byte[] placeholder = new byte[64*1024*1024];
}
}

对应的输出如下,可以看到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的周期.例如

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

在线程sleep的三秒内,可能jvm已经进行了好几次ygc.但是由于placeholder一直持有这个大对象,所以造成这个64M的大对象一直无法被回收,甚至有可能造成了满足进入old 区的条件.这个时候,在sleep之前,显式得把placeholder设置成Null是有意义的. 但是,如果没有这个耗时的操作,main方法可以非常快速的执行结束,方法返回,同时也会销毁对应的栈帧.那么就是回到第一个条件,方法已经执行结束,在下一次gc的时候,自然就会把对应的"垃圾"给回收掉.

没有满足JIT编译条件

jit编译的触发条件,这里就不多阐述了.对应的测试代码和前面一样

 public class Test
{
public static void main(String[] args) throws Exception{
byte[] placeholder = new byte[64*1024*1024];
placeholder = null;
//do some time-consuming operation
System.gc();
}
}

在解释执行中,我们认为placeholder = null;是有助于对这个大对象的回收的.在JIT编译下,JIT编译器进行控制流和数据流分析后,生成的OopMap就提供比较精确的信息,不需要通过”=null”来告知对象使命已经完成.退一步说,这时即使有”=null”操作,也会被优化掉,生成出来的本地代码与没有”=null”操作的版本是一模一样的.

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

java中将对象引用设置为null对于GC有没有帮助的更多相关文章

  1. java引用被设置为null的疑惑

    a=null; public class C { protected A webDigester = new A(" first one "); public void test( ...

  2. Java中9种常见的CMS GC问题分析与解决

    1. 写在前面 | 本文主要针对 Hotspot VM 中"CMS + ParNew"组合的一些使用场景进行总结.重点通过部分源码对根因进行分析以及对排查方法进行总结,排查过程会省 ...

  3. Java虚拟机笔记(二):GC垃圾回收和对象的引用

    为什么要了解GC 我们都知道Java开发者在开发过程中是不需要关心对象的回收的,因为Java虚拟机的原因,它会自动回收那些失效的垃圾对象.那我们为什么还要去了解GC和内存分配呢? 答案很简单:当我们需 ...

  4. WPF中未将对象引用设置到对象的实例

    前几天,我开始了WPF的基础学习,一上来我就遇到了一个令我头痛的问题,按照书上的例子我写了一段属于自己的代码,一个简单的色调器.满心期待的编译运行,就出现了未将对象引用设置到对象的实例.我在网上查阅了 ...

  5. System.Web.HttpContext.Current.Server.MapPath("~/upload/SH") 未将对象引用设置为实例对象

    做项目的时候,System.Web.HttpContext.Current.Server.MapPath("~/upload/SH")   获取路径本来这个方法用的好好的 因为需要 ...

  6. C#未将对象引用设置到对象的实例

    未将对象引用设置到对象的实例,这个错误的意思是对象为null,但你还要去取里面的值,所以计算机就不干了.解决办法一般是:用一个你不能确定是不是为null的对象时,尽量做个判断.if(object!=n ...

  7. java窗口按钮设置五个方向

    java窗口按钮设置五个方向 代码如下: package Day08; import java.awt.BorderLayout;import javax.swing.JButton;import j ...

  8. linq to sql 左联接出错,未将对象引用设置到实例

    var result = from a in model join b in orderDetailModel on a.FoodMenuID equals b.FoodMenuID into g f ...

  9. 出现"未将对象引用设置到对象的实例“问题的总结

    今天做机房收费系统时,将DataGridView中的数据导入到Excel中,当运行到这一句代码”xlApp.Cells(rows + 2, j + 1) = DataGridView1(j, rows ...

随机推荐

  1. jmeter 参数化大数据取唯一值方式

    jmeter 参数化大数据取唯一值方式 一.用时间函数: 因为时间戳永远没有重复,jmeter参数化,而且要取唯一值,可以考虑用时间函数加上其他函数一起: # 以13位的时间戳作为 userID no ...

  2. SymPy解方程的实现

    https://www.cnblogs.com/zgyc/p/6277562.html SymPy完全是用Python写的,并不需要外部的库 原理: 单纯用语言内置的运算与变量解决的是,由值求结果.如 ...

  3. 008 @Import作用

    一: 1.说明 在应用中,有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的bean,此时就需要用到@Import注解. 二:示例一 1.说明 基于007接着做的测试. 2.Bean ...

  4. WdatePicker 时间插件

    1.下载地址:链接:https://pan.baidu.com/s/1ggusfZX 密码:gu22 常用法: <input type="text" class=" ...

  5. js实现字符串切割并转换成对象格式保存到本地

    // split() 将字符串按照指定的规则分割成字符串数组,并返回此数组(字符串转数组的方法) //分割字符串 var bStr = "www.baidu.con"; var a ...

  6. index row size 2720 exceeds maximum 2712 for index "xxx" ,Values larger than 1/3 of a buffer page cannot be indexed.

    记录一个bug情况: 我有个表NewTable,复合主键(slaveid,resid,owner) CREATE TABLE "public"."NewTable&quo ...

  7. openresty开发系列33--openresty执行流程之2重写赋值阶段

    openresty开发系列33--openresty执行流程之2重写赋值阶段 一)重写赋值阶段 1)set_by_lua 语法:set_by_lua $res <lua-script-str&g ...

  8. QT中常用工具总结

    1.qmake 利用.pro文件生成Makefile 命令为: eg: qmake -o Makefile hello.pro 2. uic 利用ui界面审查.h头文件 命令为: eg: uic go ...

  9. RedisTemplate 获取redis中以某些字符串为前缀的KEY列表

    // *号 必须要加,否则无法模糊查询 String prefix = "ofc-pincode-"+ pincode + "-*"; // 获取所有的key ...

  10. ztree实现拖拽移动和复制

    1.官网下载ztree:http://www.treejs.cn/v3/api.php 2.引入jquery.ztree.all.min.js 注意,这是基于jQuery的插件,请引入相关js 3.设 ...