找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1686

积分

0

好友

220

主题
发表于 7 天前 | 查看: 30| 回复: 0

在 JavaOne 2026 临近之际,OpenJDK 通过 Quality Outreach(版本质量共建计划)向社区发出了一条重要提醒:

JDK 27 将移除 ThreadPoolExecutor.finalize() 方法。

这看似只是删除一个“空实现”,但它背后代表着 Java 平台持续多年的一个大方向:

彻底淘汰 finalization 机制。

对于部分老项目来说,这次改动甚至可能带来 直接的编译错误。如果你计划升级到未来的 JDK 版本,这件事值得提前关注。

finalize 机制为何被弃用?

在早期 Java 中,如果对象在被 GC 回收前需要释放资源,常见做法是实现:

protected void finalize() throws Throwable

垃圾回收器会在对象不可达后调用这个方法,这一过程被称为 finalization

但这个机制长期以来问题不断:

  • 执行时机不可预测
  • 容易写出不可靠代码
  • 存在安全风险
  • 会影响性能
  • 会延长对象生命周期

随着 Java 7 引入 try-with-resources,后续又推出 Cleaner API[1],官方逐渐明确态度:

finalize 应该被淘汰。

时间线大致如下:

  • JDK 9 起逐步减少 JDK 内部 finalize 使用
  • JDK 18(JEP 421)将 finalization 标记为“将移除”
  • 后续版本持续清理
  • JDK 27:继续删除遗留 finalize 实现

ThreadPoolExecutor.finalize() 的演进与影响

ThreadPoolExecutor 曾经包含一个 finalize() 方法,但它已经经历了多轮弱化:

版本 状态
JDK 9 标记为 deprecated
JDK 11 改为空实现
JDK 18 标记为将移除
JDK 27 正式删除

也就是说:

这个方法已经 什么都不做很多年

但 JDK 27 会把它彻底移除。问题在于:

删除它仍然会影响现有代码。

原因在于 Object.finalize() 的异常签名:

protected void finalize() throws Throwable { }

ThreadPoolExecutor.finalize() 不抛异常:

protected void finalize() {}

过去如果你的 ThreadPoolExecutor 子类这样写:

@Override
protected void finalize() {
    super.finalize();
}

或在其他地方直接调用 ThreadPoolExecutor.finalize(),编译器认为调用的是:

ThreadPoolExecutor.finalize()

不会抛异常。

但在 JDK 27 中,这个方法被删除后:

  • 调用会落到 Object.finalize()
  • 它声明 throws Throwable
  • 编译器要求处理异常

结果就是:

旧代码可能在 JDK 27 上直接编译失败。

这就是典型的 source incompatible change(源码不兼容变更)

影响主要集中在以下场景:

  • 自定义线程池继承 ThreadPoolExecutor
  • 框架内部封装线程池
  • 老旧代码仍实现 finalize
  • 手动调用 super.finalize()

特别是一些历史较长的企业项目或开源库,需要重点检查。

替代方案与迁移建议

OpenJDK 的建议很明确:

不要修补 finalize,应该彻底移除。

推荐替代方案:

1. try-with-resources

try (ExecutorService pool = ...) {
    // use
}

2. 显式 shutdown

executor.shutdown();

3. Cleaner API

Cleaner cleaner = Cleaner.create();
cleaner.register(obj, () -> cleanup());

这些方式都比 finalize 更可预测、更安全。

如果短期内无法删除 finalize,可以使用临时方案:

@Override
protected void finalize() {
    try {
        super.finalize();
    } catch (Throwable ignored) {
    }
}

但要注意:

  • Object.finalize() 实际为空实现
  • 只是为了编译通过
  • 不应该长期保留

更清晰的 Java 演进方向

ThreadPoolExecutor.finalize() 的移除只是 Java 清理历史机制的一部分。近年来 Java 的方向非常清晰:

旧机制 新方向
finalize try-with-resources / Cleaner
Thread.stop interrupt
SecurityManager 新安全模型
隐式资源释放 显式生命周期管理

Java 正在变得:

  • 更可预测
  • 更安全
  • 更高性能
  • 更现代

如果你的项目未来会升级 JDK 27,建议现在就开始排查。

1. 搜索代码

finalize(
super.finalize(

2. 用 EA 版本测试
使用 JDK 27 EA 跑 CI。

3. 清理 finalize
特别是线程池相关实现。

References

[1] Cleaner API: https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/ref/Cleaner.html




上一篇:借助HFS实现局域网文件快速共享:一个轻量级的HTTP文件服务器工具
下一篇:Lumen全局光照引擎实战入门:从零构建最小可运行系统
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 11:43 , Processed in 0.715046 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表