【JDK】版本特性

【一】JDK核心版本

JDK 版本分为 Oracle JDK(商业版) 和 OpenJDK(开源参考实现)。
JDK8:LTS,史上使用最广
JDK11:第二个 LTS,取消 JavaEE,移除 JAX‑WS 等
JDK17:当前主流 LTS,很多企业新项目基线
JDK21:最新 LTS,虚拟线程正式发布,新一代基线

LTS 长期支持版本:8、11、17、21,生产环境优先选 LTS;非 LTS(9,10,12‑16,18‑20)属于短期版本,只用于体验新特性,不建议上生产。

【二】版本细节

【1】JDK 8(LTS,2014)⭐ 企业存量最多

(1)核心新特性

(1)Lambda 表达式 + 函数式接口,函数式编程,Stream 流式集合处理
(2)Stream API,集合流式操作,替代大量 for 循环
(3)接口支持默认方法 default、静态方法,接口可以写实现逻辑
(4)Optional,解决空指针
(5)新时间日期 API java.time(LocalDateTime、LocalDate、Instant),替代老旧 Date/Calendar
(6)Nashorn JavaScript 引擎,可以在 Java 调用 JS
(7)并行数组操作、CompletableFuture 异步编程
(8)PermGen 永久代移除 → Metaspace 元空间(堆外内存)

(2)缺点 / 局限

(1)没有模块系统;
(2)GC:G1 是实验性,默认还是 Parallel GC;
(3)没有 var 局部变量推断;
(4)没有记录类、密封类;
(5)Oracle JDK8 从 2019 年 1 月后商业使用需要付费;OpenJDK8 免费。

【2】JDK11(LTS,2018)⭐ 过渡主流 LTS

第一个完全基于 OpenJDK 的 LTS,Oracle JDK 不再免费商用。

(1)重要变化

(1)移除 Java EE 模块:JAXB、JAX‑WS、JAX‑B、CORBA 直接删除。
升级 JDK11 老项目经常踩坑:需要手动引入 maven 依赖补回 javax.xml 相关包。
(2)支持直接运行 java 源码:java Hello.java,不用先 javac 编译;
(3)HTTP Client API(标准化,替代 HttpURLConnection);
(4)ZGC 实验性(低延迟 GC);
(5)Epsilon GC(无操作 GC,测试用);
(6)Nashorn JS 引擎被移除;
(7)不再提供 JRE,只有 JDK;想要 JRE 需要自己 jlink 打包;
(8)支持单文件源码运行。
GC 现状:默认 G1;ZGC 只是实验,不能生产用。

很多中间件、框架基线:SpringBoot2.5 + 支持 JDK11。

(2)重点变更

移除 JavaEE 相关模块(JAXB、JAX‑WS、CORBA)

JDK8 内置的javax.xml.bind.*、javax.jws等包,JDK11 直接从 JDK 中删除,不再自带。

场景 1:老项目使用 JAXB 做 xml 序列化 / 反序列化。
案例:老财务系统,XML 报文解析,JDK8 跑正常;升级 JDK11 直接报ClassNotFoundException: javax.xml.bind.JAXBContext。
解决方案:手动引入 maven 依赖

<!-- jaxb 补全 -->
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
</dependency>
不再提供独立 JRE,只有 JDK 包

JDK8 有单独 JRE 包;JDK11 开始,官方不再提供 JRE。
场景:容器化部署、生产环境裁剪 JRE。
案例:旧运维脚本下载 jre 包部署,升级 JDK11 后脚本失效。
解决方案:使用jlink自定义裁剪 JRE,或者直接使用完整 JDK 镜像。

Nashorn JS 引擎被移除

场景:老系统动态执行 JS 脚本、规则引擎。
案例:风控系统使用 Nashorn 执行动态配置的 JS 规则,升级 JDK11 直接报错。
方案:替换 Graal‑JS,或者把规则改成 Groovy/Aviator。

Oracle JDK 商业收费,必须切换 OpenJDK

场景:企业生产环境。
案例:很多公司继续使用 Oracle JDK8,没有升级 OpenJDK,收到 Oracle 商业授权告知。
方案:切换为 OpenJDK / Amazon Corretto / Eclipse Temurin。

HTTP Client 正式孵化(JDK11 内置)

场景:内部 http 调用,不再依赖 OkHttp、HttpClient 第三方包。
案例:微服务内部简单 http 调用,直接使用java.net.http.HttpClient,减少第三方包依赖。

【3】JDK17(LTS,2021)⭐ 当前企业首选基线

现在新系统首选,大量框架官方推荐版本(SpringBoot3 最低 JDK17)

(1)核心特性

(1)Records 记录类:简单数据载体,不用写 POJO 模板代码

public record User(Long id,String name){}

(2)Sealed Classes 密封类,限制继承,增强面向对象安全性
(3)Pattern Matching for switch(模式匹配预览)
(4)增强的伪随机数 API;
(5)强封装 JDK 内部 API,反射不能访问 sun.misc 等内部类;
(6)ZGC、ShenandoahGC 成熟可用;
(7)移除 Applet;
(8)很多预览特性转正。

重点:SpringBoot3、Spring6 最低要求 JDK17;Jakarta EE9 + 基线 JDK17。
迁移注意:老项目如果依赖 sun 内部 API,升级 17 会报错。

(2)重大变更

强封装 JDK 内部 API(sun.misc.、sun.reflect.

JDK9 开始模块化,JDK17 彻底收紧。
JDK8:可以反射访问sun.misc.Unsafe等内部类;
JDK17:默认禁止,即使反射也无法访问。

场景 1:高性能工具类、序列化框架
案例 1:Dubbo、Netty、Jackson、Fastjson1。
Fastjson1 大量使用Unsafe做对象内存操作,JDK17 直接报错无法运行。
真实线上案例:业务升级 JDK17,Fastjson1 反序列化直接崩溃。
✅解决方案:升级 Fastjson2,或者替换 Jackson。

案例 2:Netty 旧版本依赖 Unsafe,低版本 Netty 在 JDK17 报警告、性能下降。
解决方案:升级 Netty 版本。
临时兼容手段(不推荐生产):启动参数加–add‑opens放开模块权限,只是临时过渡,治标不治本。

预览特性转正 Record、Sealed 密封类

(1)Record 记录类
场景:DTO、BO、内部数据载体,接口返回对象,入参对象。
案例:微服务接口入出参,以前写大量 POJO:getter、setter、toString、equals。
适合:不可变数据载体;不适合需要 setter 修改的业务对象。

// JDK8 几十行代码
public class UserDTO {
    private Long id;
    private String name;
    // get set toString equals hashCode
}

// JDK17 Record,一行搞定
public record UserDTO(Long id, String name) {}

(2)Sealed Classes 密封类
场景:业务枚举替代、状态机,限制哪些子类可以继承父类。
案例:订单状态,只允许固定几个子类,防止随意扩展。
业务收益:编译期限制继承,减少运行时异常,状态机业务非常好用。

public sealed interface OrderStatus permits CreateOrder, PayOrder, CloseOrder {}
ZGC 正式生产可用

JDK11 ZGC 还是实验;JDK17 ZGC 可以生产使用。
场景:大堆内存服务(4G‑16G 以上),追求低停顿。
案例:订单、网关服务,堆内存 8G,G1 GC FullGC 停顿 1‑3 秒,接口超时。
切换 ZGC,停顿时间控制在10ms 级别。
JVM 参数:‑XX:+UseZGC

JDK17 升级典型坑总结:
Fastjson1、旧版本 Netty、旧的反射工具直接挂;
SpringBoot 必须升级到 2.7+,想要 SpringBoot3 必须 JDK17;
很多老旧自研工具类调用 sun 内部 API 直接报错。

【4】JDK21(LTS,2023)⭐ 新一代长期支持版本

下一个时代的 LTS,虚拟线程正式 GA,新项目可直接上

(1)重磅新特性

✅ 虚拟线程 Virtual Threads 正式发布
轻量级线程,开销极小,百万级别线程,极大简化异步 IO 业务,告别线程池复杂调优。

Thread.ofVirtual().name("vt-").start(() -> {});

(2)模式匹配 Switch 正式转正

Object o = "abc";
String res = switch(o){
    case String s -> "字符串:"+s;
    case Integer i -> "数字:"+i;
    default -> "其他";
};

(3)序列集合 Sequenced Collections,统一有序集合接口;
(4)结构化并发(预览);
(5)ZGC 持续优化;
(6)字符串模板(预览)。
SpringBoot3.2 + 完整支持 JDK21。

(2)重大变更

虚拟线程 Virtual Threads

JDK21 LTS,最大的变化:虚拟线程 Virtual Threads GA 正式发布。
这是 JDK 几十年来线程模型重大升级。

传统平台线程:操作系统线程,占用栈内存大,线程数量有限,几百到几千就到瓶颈。
虚拟线程:JVM 管理轻量级线程,占用极小,可以轻松创建百万级虚拟线程。
✅适用场景:IO 密集型业务,数据库查询、RPC 调用、HTTP 调用、MQ 消费,大部分时间在等待 IO。
❌不适合:CPU 密集型计算(大量循环计算,CPU 打满,虚拟线程没有收益)。

(1)业务案例 1:网关、批量调用第三方接口
场景:批量调用多个外部 http 接口,JDK8/17 需要手动创建线程池,配置 corePoolSize/maxPoolSize,参数调优很麻烦。

// JDK21虚拟线程,不需要手动线程池
for (String url : urlList) {
    Thread.ofVirtual().start(() -> httpClient.get(url));
}

以前:要自定义线程池,限制最大线程数,防止线程爆炸;
现在 IO 等待场景,直接开虚拟线程,不用复杂线程池调优。

(2)业务案例 2:MQ 消费,每条消息一个虚拟线程
RocketMQ/Kafka 消费,每条消息启一个虚拟线程处理,不再受线程池大小限制。
注意:数据库连接池依然有限,虚拟线程多,连接池必须配置合理,虚拟线程不会解决连接池瓶颈。
⚠️真实踩坑案例:
业务直接大量创建百万虚拟线程,并发访问数据库,连接池瞬间耗尽,大量等待。
👉关键点:虚拟线程解决线程本身开销,不能解决下游资源限制(数据库连接、http 连接)。

Switch 模式匹配(正式 GA JDK21)

场景:对象分支判断,大量 instanceof。
案例:订单不同类型处理,以前大量if(obj instanceof A)强转。
大量消除instanceof + 强制类型转换样板代码。

String res = switch (obj) {
    case OrderCreate o -> "创建订单:" + o.orderId();
    case OrderPay o -> "支付订单:" + o.payNo();
    default -> "未知";
};
Sequenced Collections 有序集合

场景:需要获取第一个、最后一个元素的 List/Set。
案例:以前LinkedHashSet拿最后一个元素要转迭代器,现在直接getFirst() getLast()。

【三】升级历程

【1】GC

(1)默认GC处理器
JDK8:Parallel GC
JDK8之后:G1

(2)ZGC
JDK8(LTS):无
JDK11(LTS):实验
JDK17(LTS):生产可用
JDK21(LTS):高度优化

(3)GC 小结:
ParallelGC:JDK8 默认,高吞吐,停顿长
G1:JDK9 后默认,平衡吞吐和延迟
ZGC:低延迟,百毫秒级停顿,大堆首选,17 开始稳定,21 进一步优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值