От финализаторов к детерминированному освобождению ресурсов
Замените финализацию на AutoCloseable, используя Cleaner только как защитный резервный механизм.
@Override
protected void finalize() throws Throwable {
nativeHandle.release();
}
final class NativeResource implements AutoCloseable {
private static final Cleaner CLEANER = Cleaner.create();
private static final class State implements Runnable {
private final long handle;
State(long handle) {
this.handle = handle;
}
@Override
public void run() {
release(handle);
}
}
private final Cleaner.Cleanable cleanable;
NativeResource(long handle) {
cleanable = CLEANER.register(this, new State(handle));
}
@Override
public void close() {
cleanable.clean();
}
}
Детерминированность
Try-with-resources освобождает ресурсы в известный момент.
Безопасный жизненный цикл
Исключает воскрешение финализатором и непредсказуемый порядок.
Защитный резервный механизм
Cleaner может освободить потерянные ресурсы без переопределения finalize().
Cleaner и объявление финализации устаревшей доступны начиная с JDK 9 (сентябрь 2017)
Финализация объявлена устаревшей с намерением удаления и не обеспечивает ни своевременной очистки, ни надёжного порядка. Реализуйте AutoCloseable, чтобы вызывающий код мог детерминированно освобождать ресурсы с помощью try-with-resources. Для потерянных ресурсов Cleaner в крайнем случае может вызвать то же идемпотентное действие очистки; это действие не должно удерживать зарегистрированный объект.