finalize方法不能可靠用于对象“最后一次拯救”,它不保证执行、不保证及时性、自Java 9起被弃用、Java 18默认禁用,且对象复活不可靠、状态易损坏、无二次清理机会。

Java 中的 finalize 方法**不能可靠地用于“最后一次拯救”对象**,它既不保证执行,也不保证及时执行,更不推荐用于资源清理或对象复活。自 Java 9 起已被标记为 @Deprecated,Java 18 开始默认禁用(可通过 JVM 参数开启,但不建议)。
finalize 的设计本意与现实限制
该方法原本设想在垃圾回收器准备回收对象前,由 JVM 自动调用一次,供开发者执行清理逻辑(如关闭文件、释放 native 资源)。但实际中存在严重问题:
-
不保证调用:JVM 可能在退出前不触发 GC,
finalize永远不会执行; - 不保证顺序和时机:可能延迟数秒甚至更久,无法预测何时被调用;
-
只调用一次:即使在
finalize中让对象重新可达(即“复活”),JVM 也不会再次调用它; - 性能开销大:启用 finalize 的对象会被放入专门队列,延长 GC 周期,拖慢整个堆回收。
所谓“拯救”——对象复活的危险操作
技术上,你可以在 finalize 方法中将 this 赋值给某个静态引用或全局容器,使对象重新可达,从而避免被回收。例如:
public class Rescuable {
private static Rescuable saved;
@Override
protected void finalize() throws Throwable {
System.out.println("finalize called");
saved = this; // 让对象重新被引用 → “复活”
super.finalize();
}
}
但这种做法极不可靠:
立即学习“Java免费学习笔记(深入)”;
- 复活后对象状态可能已损坏(如 native 资源已被释放、字段被重置);
- 无法控制复活时机,可能引发竞态或 NPE;
- JVM 不会再次调用
finalize,若该对象后续再次不可达,将直接回收,无第二次机会。
现代替代方案:安全、可控、可预测
真正需要“最后清理”或“资源保障”,应使用以下标准方式:
-
显式关闭 + try-with-resources:对实现
AutoCloseable的资源(如FileInputStream、Connection),用try自动调用close(); -
Cleaner(推荐):Java 9+ 提供的轻量级、非阻塞、可注册清理动作的机制,基于虚引用(
PhantomReference),不干扰 GC,且可取消; - Runtime.addShutdownHook():适用于 JVM 关闭前的全局清理(如保存缓存、关闭线程池),但不适用于单个对象生命周期管理;
-
显式生命周期管理:让调用方负责调用
dispose()、shutdown()等方法,配合文档和静态检查工具(如@MustBeClosed)提升可靠性。
总结:别依赖 finalize,也别尝试“拯救”
finalize 是历史遗留机制,语义模糊、行为不确定、性能差、易出错。对象“复活”不是设计特性,而是副作用,且违背 JVM 内存模型的确定性假设。所有需要资源清理或状态保障的场景,都应转向 Cleaner、try-with-resources 或显式管理。把 finalize 当成一个早已失效的开关,彻底忽略它,是写出健壮 Java 代码的第一步。


















