Java 对象字段的终结
我很难理解JavaSE8语言规范第12.6.1节和第12.6.2节的含义。我正在使用一种产品,其中Java对象管理本机对等点,因此正确完成(直到我们有机会重写ref队列)非常重要 从规范中可以明显看出,终结器可能会无序运行。这是可达性,我有一个困难的时间 我相信规范中说:Java 对象字段的终结,java,finalizer,Java,Finalizer,我很难理解JavaSE8语言规范第12.6.1节和第12.6.2节的含义。我正在使用一种产品,其中Java对象管理本机对等点,因此正确完成(直到我们有机会重写ref队列)非常重要 从规范中可以明显看出,终结器可能会无序运行。这是可达性,我有一个困难的时间 我相信规范中说: class A { public Object o = new Object() protected synchronized void finalize() throws Throwable { o = nu
class A {
public Object o = new Object()
protected synchronized void finalize() throws Throwable { o = null; }
}
class B {
A a = new A()
protected void finalize() throws Throwable {
a.getClass() // always works: a cannot be null.
a.o.getClass() // might NPE: a's finalizer might have been run
}
}
class C {
A a = new A()
protected void finalize() throws Throwable {
synchronized (a) {
a.getClass() // always works: a cannot be null.
a.o.getClass() // always works: a.o cannot be null.
}
}
}
上面有4个断言。我非常希望确认它们是真的,或者解释为什么一个或多个是假的。如果
A.finalize
首先获得锁,那么A.o.getClass()
即使在C
中也会NPE。最后的断言是不正确的
关于可达性,可以这样想:假设A
和C
是循环可达的,那么在“同时”将达到不可达性。因此,A
必须在C
之前完成,这是不合理的
我想一个直接的解决办法可能是
a
的引用计数。然而,依靠GC清除非内存资源并不是一件好事。正确地完成任务时要格外小心,因为完成任务基本上只能在对象未正确处理的情况下用作故障保护。正如您所注意到的,它周围的保证很少。大多数做您正在谈论的事情(例如SWT)的库都明确地要求使用dispose
方法或类似方法,而Java try with resources使处理变得更简洁。对。愚蠢的例子。在a完成之前,C可能不会抓住a上的锁。菲。你相信其他3个断言是准确的吗?我不理解你关于可达性的讨论:问题是A可能在B或C之前完成。@G.BlakeMeike-Yup<代码>A可能在B
或C
之前完成,即使它们在引用A
之前完成。即使A
有一个字段public,这也是正确的
和C
有一个构造函数C(){a.C=this;}
。是的。如果我理解正确的话,构造函数的问题似乎无关紧要。重要的是,无论最终确定的顺序如何,B和C都不会将字段“a”视为null。A的实例可能已经定稿,但引用从来都不是空的。我希望编辑可以直接回答这个问题。尽管如此,答案依然存在。。。如果隐藏在评论中。@G.BlakeMeike是的。我想是在最后一次使用和最终定稿之间。