2回复
4年前
对象回收finalize referent调用问题
需求:
资源通过引用计数控制是否可以被释放,在使用过程中,当获取资源后,需要在使用完毕后返还计数,这里通过对象被gc时的finalize referent方法来返还计数,这里就出现一个奇怪的现象了,如下代码中,是否执行一条输出1字符的代码会影响finalize referent方法是否执行,如果注释掉打印那行代码,断言失败,如果执行,则断言成功,百思不得解。
尝试去看了下字节码,也没有看到特别的指令。
public class FinalizeRefTest {
@Test
public void testFinalize() {
AtomicInteger count = new AtomicInteger(0);
Object a = FinalizeRef.wrap(new Object(), count::incrementAndGet);
System.out.println(a);
a = null;
System.gc();
System.out.println("1"); // 本行是否执行会影响下一行的断言
assertEquals(1, count.getAndIncrement());
}
}
FinalizeRef代码
import com.google.common.base.FinalizableReferenceQueue;
import com.google.common.base.FinalizableWeakReference;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import java.lang.ref.Reference;
import java.util.Set;
public final class FinalizeRef {
private static final FinalizableReferenceQueue frq = new FinalizableReferenceQueue();
private static final Set<Reference<?>> references = Sets.newConcurrentHashSet();
public static <V> V wrap(V ref, Runnable runnable) {
references.add(new FinalizableWeakReference<V>(ref, frq) {
@Override
public void finalizeReferent() {
references.remove(this);
try {
runnable.run();
log.warn("resource has been garbage collected");
} catch (Exception e) {
log.error("failed to release resource", e);
}
}
});
return ref;
}
}
2985 阅读