引用设成null对GC有帮助吗?

本文探讨了在Java中显式将对象设置为null对垃圾回收的影响。通过对比实验展示了在不同情况下,此操作是否有助于内存回收,并分析了HotSpot VM在解释执行与JIT编译时的行为差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自: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”没有意义。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值