gpt4 book ai didi

java - Java 可以在对象仍在范围内时完成对象吗?

转载 作者:搜寻专家 更新时间:2023-11-01 03:49:49 25 4
gpt4 key购买 nike

我一直在调查我的代码中的一个错误,它似乎是由一些“丑陋的”终结器代码引起的。代码大概是这样的

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 并由终结器完成thread - 当 for 循环仍在发生时,使用 ba 仍在“范围内”。

这合理吗? java 是否允许在对象超出范围之前对其进行 GC?

注意:我知道在终结器中做任何事情都是不好的。这是我继承并打算修复的代码——问题是我是否正确理解了根本问题。如果这是不可能的,那么我的错误的根源一定是更微妙的东西。

最佳答案

Can Java finalize an object when it is still in scope?

是的。

但是,我在这里很迂腐。 Scope 是一个语言概念,决定了名称的有效性。对象是否可以被垃圾收集(并因此被最终确定)取决于它是否可达

answer from ajb几乎通过引用 JLS 的重要段落来获得它(+1)。但是我不认为它直接适用于这种情况。金力士§12.6.1还说:

A reachable object is any object that can be accessed in any potential continuing computation from any live thread.

现在考虑将其应用于以下代码:

class A {
@Override protected void finalize() {
System.out.println(this + " was finalized!");
}

public static void main(String[] args) {
A a = new A();
System.out.println("Created " + a);
for (int i = 0; i < 1_000_000_000; i++) {
if (i % 1_000_000 == 0)
System.gc();
}
// System.out.println(a + " was still alive.");
}
}

在 JDK 8 GA 上,这将每次都完成 a。如果您在最后取消注释 printlna 将永远不会完成。

通过注释掉 println,可以看出可达性规则是如何应用的。当代码到达循环时,线程无法访问 a。因此它是不可访问的,因此要进行终结和垃圾收集。

请注意,名称 a 仍在范围内,因为可以在封闭 block 内的任何地方使用 a -- 在这种情况下 main 方法体——从它的声明到 block 的末尾。 JLS §6.3 中涵盖了确切的范围规则.但实际上,如您所见,作用域与可达性或垃圾回收无关。

为了防止对象被垃圾回收,您可以在静态字段中存储对它的引用,或者如果您不想这样做,您可以通过稍后在相同的方法中使用它来保持它的可访问性耗时的循环。在其上调用诸如 toString 之类的无害方法就足够了。

关于java - Java 可以在对象仍在范围内时完成对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31575565/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com