finalize()是Object类中由JVM在对象即将被回收前自动调用的protected临终回调方法,自Java 9起已被@Deprecated标记为过时,因性能差、不可靠且不保证执行,应优先使用try-with-resources或Cleaner替代。

finalize() 方法是 Object 类中一个被标记为 protected 的空方法,它不是用来手动调用的,而是由 JVM 垃圾回收器在对象**即将被回收前自动触发**的一次回调机会。
finalize 是一个“临终回调”,不是清理入口
它本质上是 JVM 提供给程序员的一个“对象销毁前通知机制”,类似静态代码块之于类加载——属于特定生命周期的钩子。但要注意:
- 它不保证一定会被执行:GC 可能长期不启动,或对象被重新引用而逃逸回收
- 它不保证执行时机:可能延迟很久,甚至到 JVM 退出前才集中调用(如某些 GC 策略)
- 它不能替代显式资源管理:比如打开的文件、网络连接、数据库连接等,必须靠 try-with-resources 或 close() 显式释放
重写 finalize 要谨慎,且已过时
从 Java 9 开始,finalize() 已被标记为 @Deprecated,官方明确不推荐使用。原因包括:
- 性能开销大:带 finalize 的对象需经历至少两次 GC 才能真正回收(第一次标记 + 放入 F-Queue,第二次才清理)
- 行为不可控:F-Queue 中的执行顺序、线程、是否抛异常均无保障,异常会被静默吞掉
- 替代方案更可靠:Cleaner(Java 9+)、PhantomReference 配合 ReferenceQueue,或 try-finally/try-with-resources
它和 equals、toString 的调用逻辑完全不同
finalize 不是“你写了就得自己记着去调”的方法:
- equals 和 toString 是普通实例方法,需要你主动调用(如 obj.equals(other)、System.out.println(obj))
- finalize 是被动触发的:你只需重写它,JVM 在判定该对象可回收后,会自动调用一次(最多一次)
- 即使重写了,也不代表它真会被调用;即使调用了,也不能假设它一定完成或成功执行
简单说,现在该怎么做
如果你需要资源清理或善后逻辑:
- 优先用 try-with-resources(实现 AutoCloseable)
- 对非堆资源(如直接内存、本地句柄),用 Cleaner 注册清理动作
- 避免在 finalize 中做日志、同步、IO、启动线程等任何不可靠操作
- 如果遗留代码里还看到 finalize,建议逐步迁移到 Cleaner 或显式关闭流程










