finalize 方法在现代 java 中已废弃,因执行不可靠、时机不可控、拖慢 gc、线程不安全且异常被吞,应改用 try-with-resources、显式关闭、cleaner 或框架生命周期回调。

finalize 方法在现代 Java 中已不推荐使用,且自 Java 9 起被标记为 deprecated,Java 18 开始默认禁用,Java 21 中彻底移除(JEP 421)。 它无法保证执行时机、不保证一定执行、不能替代 try-with-resources 或显式资源管理,也不适用于性能敏感或可靠性要求高的场景。
为什么 finalize 不该用于对象清理
• JVM 不承诺调用 finalize:对象可能永远不被回收,或在程序退出前未触发;
• 执行时间不可控:GC 时机不确定,可能导致资源长时间泄漏(如文件句柄、网络连接);
• 可能造成 GC 延迟:含 finalize 的对象需经历两次 GC 才能真正回收(第一次标记并放入 Finalizer 队列,第二次才回收),拖慢内存释放;
• 线程安全风险:finalize 在 Finalizer 线程中运行,与应用线程异步,易引发竞态或死锁;
• 无法捕获异常传播:finalize 中抛出的异常会被 JVM 吞掉,无声失败,难以调试。
替代 finalize 的正确做法
• 优先使用 try-with-resources:对实现 AutoCloseable 的资源(如 FileInputStream、Socket、Scanner),自动调用 close();
• 显式调用清理方法:在业务逻辑结束处主动调用 close()、shutdown()、release() 等约定方法;
• 使用 Cleaner(Java 9+ 推荐):基于虚引用(PhantomReference)的轻量级、可预测的清理机制,不阻塞 GC,支持注册清理动作;
• 依赖依赖注入框架的生命周期回调:如 Spring 的 @PreDestroy、Jakarta EE 的 @PreDestroy 注解。
如果仍需兼容旧代码(不建议)
• finalize 必须声明为 protected,且不能有参数、不能有返回值;
• 不应在其中调用 super.finalize()(Object 的实现为空,但子类若重写过且依赖链式调用则需谨慎);
• 避免在 finalize 中重新使对象“复活”(如将 this 赋值给静态字段),这会阻止对象回收并导致严重内存泄漏;
• 不要指望它做关键清理(如释放数据库连接、解锁文件),必须有兜底的显式释放逻辑。
对象清理应由程序员主动控制,而不是交给不可靠的 finalize。现代 Java 已提供更安全、更可控的替代方案。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











