gpt4 book ai didi

java - java可以在对象仍在范围内时对其进行最终确定吗?

转载 作者:IT老高 更新时间:2023-10-28 20:46:28 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 和终结线程 - 当 for 循环仍在发生时,使用 ba 仍然“在范围内”。

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

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

最佳答案

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

是的。

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

answer from ajb通过引用 JLS 的重要段落,几乎得到了它(+1)。但是我不认为它直接适用于这种情况。 JLS §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。如果您在最后取消注释 println,则 a 将永远不会被最终确定。

println 注释掉后,可以看到可达性规则是如何应用的。当代码到达循环时,线程不可能访问a。因此它是不可达的,因此需要完成和垃圾回收。

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

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

关于java - java可以在对象仍在范围内时对其进行最终确定吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24376768/

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