为了账号安全,请及时绑定邮箱和手机立即绑定

当java仍然在范围内时,java能否最终确定它?

当java仍然在范围内时,java能否最终确定它?

繁星点点滴滴 2019-08-13 17:14:36
当java仍然在范围内时,java能否最终确定它?我一直在研究我的代码中的一个错误,似乎是由一些“丑陋的”终结器代码引起的。代码看起来大致如此public class A {    public B b = new B();    @Override public void finalize() {      b.close();    }}public class B {    public void close() { /* do clean up our resources. */ }    public void doSomething() { /* do something that requires us not to be closed */ } }void main() {    A a = new A();    B b = a.b;    for(/*lots of time*/) {      b.doSomething();    }}我认为正在发生的事情是a在第二行之后被检测到没有引用main()并且被终结器线程获得GC并最终确定 - 当for循环仍然发生时,使用bwhile a仍然是“在范围内”。这有可能吗?是否允许java在对象超出范围之前将其作为对象?注意:我知道在终结器中做任何事情都很糟糕。这是我继承并打算修复的代码 - 问题是我是否正确理解了根本问题。如果这是不可能的,那么更微妙的东西必定是我的bug的根源。
查看完整描述

2 回答

?
阿晨1998

TA贡献2037条经验 获得超6个赞

JLS§12.6.1

可以设计优化程序的转换,以减少可达到的对象的数量,使其少于可以被认为可达的对象的数量。例如,Java编译器或代码生成器可以选择设置将不再用于null的变量或参数,以使得此类对象的存储可能更快地被回收。

所以,是的,我认为这是允许的编译器添加隐藏代码设置anull,从而使其能够进行垃圾回收。如果发生了这种情况,您可能无法从字节码中分辨出来(请参阅@ user2357112的评论)。

可能(丑陋)的解决方法:添加public static boolean alwaysFalse = false;到主类或其他类,然后在最后main()添加if (alwaysFalse) System.out.println(a);或引用的其他内容a。我不认为优化器可以确定alwaysFalse永远不会设置(因为某些类总是可以使用反射来设置它); 因此,它无法分辨出a不再需要它。至少,这种“解决方法”可用于确定这是否确实是问题。


查看完整回答
反对 回复 2019-08-13
  • 2 回答
  • 0 关注
  • 1462 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信