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

gny*_*his 2 java garbage-collection finalize pass-by-reference

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

假设这是Thread1的骨架:

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

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

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

Tom*_*son 6

第二个线程接收相同的实际对象实例.你过早结束是安全的.

它接收对象引用的副本,如果你想这样想的话.

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