⚠️ Java продолжает готовиться к удалению finalize()
В рамках JDK 27 у ThreadPoolExecutor-а, очень популярного API в Java, будет удалён метод finalize(). Несмотря на то, что в силу dynamic dispatch вызов метода finalize() всё равно будет транслирован в Object, данное изменение не source level compatible.
А все потому, что у Object.finalize() сигнатура содержит throws Throwable, в то время как ThreadPoolExecutor.finalize() — нет. Пока метод был в ThreadPoolExecutor, компилятору было ок. Как только его удалят, вызов super.finalize() начнет резолвиться в Object.finalize(), и тогда прилетит “unreported exception Throwable”.
Комментарий от Михаила Поливаха:
Вот это кстати довольно редкий пример того, что имзенение может быть binary level compatible, но не source level compatible.
Например:
class MyPool extends ThreadPoolExecutor { @Override protected void finalize() { super.finalize(); // JDK 27: теперь это Object.finalize() throws Throwable } }
Как избежать?
поискать и удалить любые
finalize()/super.finalize()(и вообще любые авто-cleanup через финализацию)управлять жизненным циклом executor’ов явно:
shutdown()/awaitTermination()или просто close() в try-with-resources (да,ExecutorService—AutoCloseable)
Spring АйО рекомендует не использовать finalize() в целом, но если подобного рода хук нужен, то лучше использовать Java Cleaner API. С его помощью нельзя "случайно" воскресить объект, сломать integrity объекта или т.п.
Ждем JDK 27 🫠

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.
