以下是JLS(7)第12.6.1节的文本块。
例如,考虑Finalizer Guardian模式:
class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
/* finalize outer Foo object */
}
}
}
如果子类重写finalize并且没有显式调用super.finalize,则终结器监护人会强制调用super.finalize。
如果对存储在堆上的引用允许这些优化,那么Java编译器可以检测到finalizerGuardian字段永远不会被读取,将其清空,立即收集对象,并尽早调用终结器。这与意图背道而驰:程序员可能希望在Foo实例无法访问时调用Foo终结器。因此,这种转换不合法:只要外部类对象可以访问,内部类对象就应该可以访问。
此类转换可能会导致finalize方法的调用发生得比预期的要早。为了允许用户阻止这种情况,我们强制执行同步可以使对象保持活动的概念。如果对象的终结器可以导致该对象的同步,则该对象必须处于活动状态,并且只要在其上保持锁定就认为该对象是可达的。
请注意,这不会阻止同步消除:如果终结器可能同步,则同步仅使对象保持活动状态。由于终结器出现在另一个线程中,因此在许多情况下无论如何都无法移除同步。
问题1:关于最后两段,这是我们需要做的吗?
class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
synchronized(this){
/*
*Some code goes here
*/
}
/* finalize outer Foo object */
}
}
}
问题:同步发生的时间何时发生?