为什么不调用Cleaner操作?

时间:2019-02-12 14:01:00

标签: java dispose finalizer autocloseable

这是this one的后续问题。

具体地说,我正在尝试验证对API的正确使用,该API涉及对通过JNI持有大量本机资源的Java对象调用close()。为了再次回答这个问题,在测试和生产测试中都需要这样做,因为资源从一个测试用例泄漏到另一个测试用例,并且在生产中也是如此,因为本地资源应该以受控方式进行处理。

代码(我想要处理的所有此类Java对象都将扩展JPeer):

public class JPeer implements AutoCloseable {

    private final long nativeHandle_ = ....

    private final Verifier closeVerifier_;
    private static final Cleaner cleaner_ = Cleaner.create();

    protected JPeer() {
        closeVerifier_ = new Verifier();
        cleaner_.register(this, closeVerifier_);
    }

    @SuppressWarnings("unchecked")
    @Override
    public final void close() {
        if (closed())
            throw new AssertionError("JPeer already closed");

        ..... // doing dispose over JNI

        closeVerifier_.markDone();
    }



//    @SuppressWarnings("deprecation")
//    @Override
//    protected final void finalize() {
//        if (!closed()) {
//            // due to threading considerations with JNI, we shouldn't destroy here, we rely on user to destroy from construction thread
//                // TODO finalize() never called, how to assert closure?
//            throw new AssertionError("JPeer was not closed, native object leaking");
//        }
//    }

    private static final class Verifier implements Runnable {

        volatile boolean done_ = false;

        public void markDone() {
            done_ = true;
        }

        @Override
        public void run() {
            if (!done_) {
                // due to threading considerations with JNI, we shouldn't destroy here, we rely on user to destroy from construction thread
                System.err.println("Verifier: JPeer was not closed, native object leaking");
                throw new AssertionError("Verifier: JPeer was not closed, native object leaking");
            }
            else {
                System.out.println("Verifier: JPeer was closed");
            }
        }
    }
}

为什么未调用清洁器操作??我在控制台中看不到“ JPeer已关闭”或“ JPeer未关闭”。无法通过更清洁的操作打印某些内容是否有问题? (我知道从那里抛出的异常会被忽略,因此AssertionError毫无用处)。如果是这样,我如何通知我的验证结果?

0 个答案:

没有答案