I/O Zaawansowany

Od finalizatorów do deterministycznego zwalniania zasobów

Zastąp finalizację interfejsem AutoCloseable, a Cleaner stosuj tylko jako awaryjne zabezpieczenie.

✕ 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();
    }
}
Widzisz problem z tym kodem? Daj nam znać.
⏱

Deterministyczność

Try-with-resources zwalnia zasoby w znanym momencie.

🛡

Bezpieczniejszy cykl życia

Eliminuje wskrzeszanie obiektów przez finalizator i nieprzewidywalną kolejność.

🧹

Awaryjne zabezpieczenie

Cleaner może odzyskać zasoby po wycieku bez przesłaniania finalize().

Stare podejście
Przesłanianie finalize()
Nowoczesne podejście
AutoCloseable i Cleaner
Od JDK
9
Poziom trudności
Zaawansowany
Od finalizatorów do deterministycznego zwalniania zasobów
Dostępne

Cleaner i oznaczenie finalizacji jako przestarzałej są dostępne od JDK 9 (wrzesień 2017)

Finalizacja jest przestarzała i przeznaczona do usunięcia; nie zapewnia ani szybkiego zwalniania zasobów, ani niezawodnej kolejności. Zaimplementuj AutoCloseable, aby kod wywołujący mógł deterministycznie zwalniać zasoby za pomocą try-with-resources. W przypadku wycieku zasobów Cleaner może w ostateczności wywołać tę samą idempotentną operację czyszczenia; jego akcja nie może przechowywać referencji do zarejestrowanego obiektu.