性能问答>对象回收finalize referent调用问题>
2回复
1年前

对象回收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;
    }

}
2643 阅读
请先登录,查看2条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步