finalize: устаревший механизм
Object.finalize() задумывался как последний шанс освободить внешний ресурс перед удалением объекта. На практике JVM не гарантирует ни время, ни сам факт вызова. Начиная с Java 9 механизм устарел, позднее помечен к удалению. В новом коде его использовать нельзя.
Почему он опасен
- объект может долго ждать финализации и удерживать память;
- медленный финализатор тормозит обработку остальных объектов;
- исключение из
finalize()игнорируется; - объект можно «воскресить», сохранив
thisв достижимом месте; - порядок финализации связанных объектов не определён;
- финализация не заменяет транзакцию и не гарантирует освобождение файла, сокета или соединения.
// Правильно: ресурс закрывается явно.
class Report implements AutoCloseable {
private final InputStream input;
Report(Path path) throws IOException {
input = Files.newInputStream(path);
}
@Override
public void close() throws IOException {
input.close();
}
}
try (Report report = new Report(path)) {
// работа с отчётом
}Для ресурсов с явным жизненным циклом нужны AutoCloseable и try-with-resources. Cleaner и ссылки из java.lang.ref годятся только как страховочная сетка для редких низкоуровневых случаев: они тоже не дают своевременной гарантии.
Не путать
finalize, final и finally не связаны:
| Конструкция | Назначение |
|---|---|
finalize() | устаревший callback перед возможным удалением объекта |
final | запрет повторного присваивания, переопределения или наследования |
finally | блок очистки после try/catch |
На собеседовании
Гарантирован ли вызов finalize()? Нет. Процесс может завершиться раньше, а JVM не обязана финализировать все объекты.
Можно ли закрывать JDBC-соединение в finalize()? Нет. Закрывать нужно явно, обычно через try-with-resources.
Чем заменить финализатор? Управляемым жизненным циклом (close), а при необходимости резервной очистки — Cleaner, понимая его ограничения.
Связано: Процесс сборки мусора, Виды ссылок в java.