I/O Продвинутый

От финализаторов к детерминированному освобождению ресурсов

Замените финализацию на AutoCloseable, используя Cleaner только как защитный резервный механизм.

✕ Finalization
@Override
protected void finalize() throws Throwable {
    nativeHandle.release();
}
✓ Java 9+
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().

Старый подход
Переопределение finalize()
Современный подход
AutoCloseable и Cleaner
Начиная с JDK
9
Сложность
Продвинутый
От финализаторов к детерминированному освобождению ресурсов
Доступно

Cleaner и объявление финализации устаревшей доступны начиная с JDK 9 (сентябрь 2017)

Финализация объявлена устаревшей с намерением удаления и не обеспечивает ни своевременной очистки, ни надёжного порядка. Реализуйте AutoCloseable, чтобы вызывающий код мог детерминированно освобождать ресурсы с помощью try-with-resources. Для потерянных ресурсов Cleaner в крайнем случае может вызвать то же идемпотентное действие очистки; это действие не должно удерживать зарегистрированный объект.