在这种情况下,什么时候在我的类实例上调用finalize()?

时间:2011-07-21 15:55:22

标签: java garbage-collection pass-by-reference finalize

我知道每当垃圾收集器收集一个类实例时都会调用finalize()。但是,当通过队列将类的实例传递给另一个线程时,我有点困惑。

假设这是Thread1的骨架:

for(i=0; i<1000; i++) {
   Packet pkt = new Packet();  // instance of class
   pkt.id = i;
   thread2.queue.put(pkt);
}

然后,线程2将从队列中删除数据包并执行冗长的操作。这第二个线程是否获得了数据包的“副本”,还是通过某种形式的引用?重要的是,如果是通过复制,则可以在线程2完成数据包之前调用在线程1中创建的实例上的finalize()。如果它是通过引用,我保证只对包中的信息调用finalize()一次。

这个基本示例可能没有显示重要性,但我在数据包中存储了一个C指针(来自JNI),以便在完成对象时销毁一些内存。如果它是通过副本传递的,则内存可能会在第二个线程完成之前被销毁。如果它是通过引用传递的,那么它应该只在GC看到它不再被两个线程使用时被销毁(我想要的行为)。如果后一种情况得不到保证,我不会使用finalize()并使用其他东西,但会更复杂。

1 个答案:

答案 0 :(得分:6)

第二个线程接收相同的实际对象实例。你不会过早结束。

如果你想这样想的话,它会收到一个对象引用的副本。

此外,当垃圾收集器发现对象已变为垃圾时,finalize不一定会运行 - VM可以在以后任何时候自由运行它,并在此之后的某个时间实际回收内存。你真的不能依赖于finalize何时运行。但是,因为你关心的是知道在第二个线程完成对象之前不会调用finalize ,这是无关紧要的。但值得知道!