Java基础、中级、高级、架构面试资料

JDK 26 释放重磅信号, 不再包容屎山代码,移除 Thread.stop

JAVA herman 13浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
【腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

这个月的 3 月 17 号,JDK 26 正式发布了,昨天我也写了对应的文章,给大家广而告之。

昨天和之前的一系列文章中,我更多讲的是 JEP 这类的新特性等内容。这次的 JDK 26 发布,还有一些非特性方面的内容很少有网友关注。后面,我就抽出一些时间来一一讲解一下 JDK 26 中容易被忽略遗忘的改进!

本文重点讲解要给,Java 老司机都熟悉的线程方法Thread.stop(),这个方法被 Java 26 正式“枪毙”了,一个被诅咒了 28 年的方法终于入土了。

早在去年 5 月份,我就写过一篇文章《https://mp.weixin.qq.com/s/twymMnZmShtQ-1iOeb-m3Q》,讲过 Java 线程的两阶段停止以及不推荐的停止方式。

  • Thread.stop():已废弃,强制停止线程可能导致对象状态不一致。类似 kill -9 一样的危害
  • Thread.suspend()、resume():已废弃,容易导致死锁

现在 Java 26 正式移除了 Thread.stop(),一个遗留 28 年的“定时炸弹”终于谢幕。它也是 Java 史上最危险的 API,还曾让无数系统数据崩溃。

文章配图参见我的公众号https://mp.weixin.qq.com/s/zucWddfzu-bPtcHCqnQW3w

JDK-8368226 到底做了什么?

JDK-8368226 虽不起眼,但由于它的历史悠久,因此也算得上是一个重磅变更了。尤其是在这个看似常规的短期支持版本中,一个看似微小但意义深远的变更java.lang.Thread.stop() 方法被彻底移除了。

文章配图参见我的公众号https://mp.weixin.qq.com/s/zucWddfzu-bPtcHCqnQW3w

根据 OpenJDK 官方发布说明 ,这次变更(编号#JDK-8368226)意味着。

  • 编译层面:调用 Thread.stop() 的代码将无法通过编译
  • 运行层面:已编译的旧代码在 Java 26 上运行时会抛出 NoSuchMethodError(而非之前的 UnsupportedOperationException

这不是一个简单的“废弃”(deprecated),而是“物理删除”。从 JDK 的源代码、字节码到运行时,这个方法彻底消失了。

黑历史回顾

要理解这次移除的意义,我们需要回顾 Thread.stop() 的“黑历史”。

时间节点事件意义
1998 年JDK 1.2 发布,Thread.stop() 被标记为 @Deprecated官方首次承认其不安全
2004 年Java 官方文档《Why Are Thread.stop, Thread.suspend and Thread.resume Deprecated?》发布详细解释了不安全原因
2022 年JDK 18 发布,标记为 @Deprecated(forRemoval = true)正式进入移除倒计时
2023 年JDK 20 发布,改为无条件抛出 UnsupportedOperationException运行时层面禁用
2026 年JDK 26 发布,方法彻底移除28 年的“废弃生涯”终结

这个方法从被标记废弃到真正移除,经历了整整 28 年,多深的包袱呀!这在 Java 历史上是罕见的超长“ deprecation 周期”。

28 年!从一个方法从废弃到删除,就可以看出 Java 的“向后兼容”到底是有多么的执着。

为什么 Thread.stop() 如此危险?

官方文档用了一句话概括:This method is inherently unsafe(这个方法本质上就是不安全的)

两大致命缺陷

当你调用 thread.stop() 时,背后会发生两件事。

  1. 即刻抛出 ThreadDeath 异常:这个异常可以在 run() 方法的任何执行点抛出,包括 catchfinally 块中
  2. 强制释放所有锁:线程持有的所有监视器(monitor)会被立即解锁

数据损坏的典型案例

想象下面这样一个场景。

public class BankTransfer {
    private double balance = 1000;
    public synchronized void transfer(double amount) {
        // 步骤1:扣减余额
        this.balance -= amount;  // 此时 balance = 500

        // 步骤2:模拟耗时操作(网络请求、日志记录等)
        Thread.sleep(5000);      // 在此期间被 stop()!

        // 步骤3:记录交易流水(永远执行不到了)
        logTransaction(amount);
    }
}

如果在 sleep 期间调用 stop(),会发生什么?

  • 交易未完成,但余额已经被扣减(balance = 500
  • 锁被释放,其他线程可以立即访问这个不一致状态的对象
  • 没有交易记录,但钱已经“消失”了

这就是官方所说的damaged objects(受损对象),处于不一致状态的对象被暴露给其他线程,可能导致任意不可预测的行为

为什么不能捕获 ThreadDeath 来修复?

理论上,你可以在catch (ThreadDeath)中做清理工作。但官方文档明确指出这几乎不可能

  1. 异常可以在任何地方抛出:你需要在每个同步块、每个方法调用处都考虑清理逻辑,代码将变得极其复杂
  2. 清理过程中可能再次抛出ThreadDeath:套娃了,你需要递归地处理清理,直到成功,这在实践中几乎无法实现

更可怕的是,ThreadDeath是一个Error,而非 Exception,它悄无声息地杀死线程,不会打印堆栈跟踪(除非你显式捕获),这也导致产生问题后极难排查。

Java 社区的移除共识

这次移除并非突然决定,而是 Java 社区多年共识的结果。

Project Loom 的推动

随着 Project Loom(虚拟线程)的推进,Java 的并发模型正在发生根本性变革。Thread.stop()这种“野蛮”的线程终止方式,与现代化、结构化的并发编程理念完全冲突。在结构化并发(Structured Concurrency)中,线程的生命周期应该是协作式、可预测、可组合的,而非被强制终止。

Java 安全性的整体提升

JDK 26 中还有另一个相关变更《JEP 500 – Prepare to Make Final Mean Final》,https://mp.weixin.qq.com/s/L0vWK5BTQrlO_huLbOtC9Q。这个特性警告使用深度反射修改final字段的行为,为未来彻底禁止这种操作做准备。

Thread.stop()的移除与这一趋势一致,即:Java 正在收紧那些破坏对象完整性、绕过语言安全机制的操作

正确停止线程的现代方案

既然 stop() 被移除了,我们应该如何正确停止线程?

方案 1 协作式中断

看下面这段代码。

public class SafeStop {
    public static void main(String[] args) throws InterruptedException {
        Thread worker = new Thread(() -> {
            // 定期检查中断状态
            while (!Thread.currentThread().isInterrupted()) {
                try {// 业余草
                    doWork();
                } catch (InterruptedException e) {
                    // 收到中断信号,清理资源后退出
                    System.out.println("收到中断信号,准备退出...");
                    cleanup();
                    break; // 或 return
                }
            }
        });

        worker.start();
        Thread.sleep(1000);
        worker.interrupt(); // 优雅地请求停止
    }
}

方案 2 volatile 标志位(推荐)

public class VolatileStop {
    private volatile boolean running = true;
    // 业余草
    public void stop() {
        running = false;
    }

    public void run() {
        while (running) {
            doWork();
        }
        cleanup();
    }
}

方案 3 结构化并发

这个结构化并发方案需要在 JDK 21+ 的版本上才能体验到。

// 使用 StructuredTaskScope 自动管理子线程生命周期
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    scope.fork(() -> {
        // 业余草 子任务1
        return doTask1();
    });
    scope.fork(() -> {
        // 业余草 子任务2  
        return doTask2();
    });

    scope.join(); // 等待所有任务完成或失败
    scope.throwIfFailed();
} // 作用域结束时,所有子线程自动、安全地停止

对现有项目的影响与迁移建议

影响范围评估

  • 直接调用 Thread.stop():编译失败,必须修改
  • 反射调用:会抛出 NoSuchMethodError
  • 遗留系统:一些老旧的库(如早期版本的某些应用服务器)可能还在使用

迁移步骤

  1. 全局搜索:在代码库中搜索 .stop() 调用
  2. 替换为中断机制:将强制停止改为 interrupt() + 协作式检查
  3. 测试边界情况:确保中断响应逻辑正确处理资源清理
  4. 升级依赖:确保第三方库已适配 Java 26

临时回退方案

如果必须运行依赖 stop() 的旧代码,则可以考虑下面两种做法。

  • 在 Java 25(LTS 版本)上运行,获得长期支持
  • 使用字节码转换工具(如 ASM)将 stop() 调用重定向到自定义的安全停止逻辑

Java 的技术债清理

Thread.stop()的移除,标志着 Java 平台正在加速清理历史遗留的技术债

近年来,我们已经看到。

  • JDK 17:移除 Applet API、Security Manager
  • JDK 21:弃用 32 位 Windows 支持
  • JDK 26:移除 Thread.stop()、Applet API(彻底移除)、InfiniBand SDP 支持

这些变更的共同点是,它们都是在 1990 年代或 2000 年代初设计的 API,在当时有其合理性,但与现代计算环境完全不兼容

Java 不再是那个“永远向后兼容”的保守平台。在保持企业级稳定性的同时,它正在有节奏地剔除那些阻碍现代化、带来安全隐患的古老特性

结语

Java 正在向“不安全”告别,也在向“永远向后兼容”告别。

Thread.stop() 的移除,是 Java 并发编程历史上的一个里程碑。它宣告了一个时代的结束:强制、不可控、破坏性的线程管理方式,终于被协作式、结构化、安全的方式取代

对于开发者来说,这既是挑战(需要检查遗留代码),也是机遇(被迫采用更健壮的并发模式)。正如官方文档所言:

能协作的线程才是好线程,需要被 stop 的线程本就不该 start。

Stop 一个线程,等于承认你的设计失败了两次:一次是让它做不该做的事,一次是你不得不杀了它。

如果你需要 Thread.stop(),那你需要的不是 stop,是重构。

28 年的等待,Thread.stop() 终于谢幕。这是 Java 平台向现代化、安全性、结构化并发迈出的坚实一步。

参考资料

  • OpenJDK JDK 26 Release Noteshttps://jdk.java.net/26/release-notes
  • Java 官方文档《Why Are Thread.stop, Thread.suspend and Thread.resume Deprecated?》
  • https://stackoverflow.com/questions/8464368/how-can-i-stop-threads-created-with-an-anonymous-class
  • https://bugs.openjdk.org/browse/JDK-8368226

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » JDK 26 释放重磅信号, 不再包容屎山代码,移除 Thread.stop