JavaGC问题:当对象的一个方法仍在执行时,该对象如何变得不可访问?

JavaGC问题:当对象的一个方法仍在执行时,该对象如何变得不可访问?,java,memory-management,garbage-collection,finalizer,Java,Memory Management,Garbage Collection,Finalizer,我一直在读关于Java终结器的书。在本文中,作者描述了一个场景(在幻灯片33上),其中,CleanResource.finalize()可由终结器线程运行,而CleanResource.doSomething()仍在另一个线程上运行。这怎么会发生 如果doSomething()是一个非静态方法,那么要执行该方法,必须在某个地方有一个对它的强引用。。。正确的?那么,如何在方法返回之前清除该引用呢?另一个线程是否可以插入并消除该引用?如果发生这种情况,doSomething()是否仍会在原始线程上正

我一直在读关于Java终结器的书。在本文中,作者描述了一个场景(在幻灯片33上),其中,
CleanResource.finalize()
可由终结器线程运行,而
CleanResource.doSomething()
仍在另一个线程上运行。这怎么会发生

如果
doSomething()
是一个非静态方法,那么要执行该方法,必须在某个地方有一个对它的强引用。。。正确的?那么,如何在方法返回之前清除该引用呢?另一个线程是否可以插入并消除该引用?如果发生这种情况,
doSomething()
是否仍会在原始线程上正常返回

这就是我真正想知道的,但要得到一个真正的高于一切的答案,你可以告诉我为什么幻灯片38上的
doSomething()
比幻灯片29上的
doSomething()
更好。为什么只调用这个
keepAlive()
方法就足够了?您不需要将对
myImpl.doSomething()
的整个调用包装在
synchronized(this){}
块中吗?

EDIT3:

结果是,终结器和常规方法可以在同一个实例上并发执行。这是一个如何发生的解释。该守则基本上是:

class CleanResource {
   int myIndex;
   static ArrayList<ResourceImpl> all;

   void doSomething() {
     ResourceImpl impl = all.get(myIndex);
     impl.doSomething();
   } 

   protected void finalize() { ... }
}
这可能会被jit到类似于伪C的东西上

register CleanResource* res = ...; call ctor etc..
// inline CleanResource.doSomething()
register int myIndex = res->MyIndex;
ResourceImpl* impl = all->get(myInddex);
impl->DoSomething();
// end of inline CleanResource.doSomething()
res = null;
这样执行,
res
在内联的
CleanResource.doSomething()
完成后被清除,因此gc将在该方法完成执行后才会发生。不可能在同一实例上与另一个实例方法同时执行finalize

但是,写入
res
在该点之后不使用,并且假设没有围栏,可以在执行的早期将其移动到写入之后:

register CleanResource* res = ...; call ctor etc..
// inline CleanResource->doSomething()
register int myIndex = res->MyIndex;
res = null;    /// <-----
ResourceImpl* impl = all->get(myInddex);
impl.DoSomething();
// end of inline CleanResource.doSomething()
注册CleanResource*res=。。。;打电话等。。
//内联CleanResource->doSomething()
寄存器int myIndex=res->myIndex;
res=null;///获取(myindex);
impl.DoSomething();
//内联CleanResource.doSomething()的结尾

在标记的位置(那么这也会发生在基于堆栈的虚拟机上吗?现在我和你一样在字节码级别思考,我对这一点的理解要好得多。我想在堆栈机器的情况下,
invokevirtual
完成时,引用不需要在堆栈上?所以一旦检索到
myIndex
值,那么
这个
can是否从堆栈中弹出并可能回收?在严格的基于堆栈的实现中,这是不可能的,因为this指针将保留在堆栈上。但通过方法内联、无序执行和寄存器分配,可以同时调用终结器。请参阅本系列文章中我的最新编辑。:)回答得很好!除了Android的Dalvik VM之外,我甚至不知道还有谁实现了基于注册的JVM。这是常见的吗?据我所知,JIT并不局限于基于堆栈的约定,例如,方法内联非常常见,因为在最近的版本中,方法内联变得更加积极,因为它允许JIT以更大的速度执行更多优化代码块。请参阅
register CleanResource* res = ...; call ctor etc..
// inline CleanResource->doSomething()
register int myIndex = res->MyIndex;
res = null;    /// <-----
ResourceImpl* impl = all->get(myInddex);
impl.DoSomething();
// end of inline CleanResource.doSomething()