这是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
毫无用处)。如果是这样,我如何通知我的验证结果?