当前位置: 首页 > news >正文

JDK 9~17 新特性及升级建议

总览

版本类别特性名称详细说明升级建议
JDK 9语言接口私有方法接口可定义 private 方法,减少重复默认实现对旧代码无影响,可在接口中重构公共逻辑
 语言流 API 增强新增 takeWhiledropWhileiterate无兼容性问题,可优化流操作
 API多版本 JAR同一 JAR 支持多版本类实现适合兼容多 JDK 版本的库开发
 平台模块化系统(Project Jigsaw)module 系统,模块化打包与依赖隔离高影响:需处理 split packages、反射访问内部 API
JDK 10语言局部变量类型推断 (var)自动推断局部变量类型无兼容性问题,代码可读性需平衡
 JVMG1 GC 改进Full GC 并行化性能提升,可直接受益
 JVM应用类数据共享(AppCDS)类元数据共享,加快启动需打包时生成共享档案
 JVMThread-Local Handshakes单线程操作无需全局停顿性能提升,无需代码改动
JDK 11APIHTTP Client(标准化)支持 HTTP/1.1 & HTTP/2,异步调用可替换旧 HttpURLConnection
 语言Lambda 参数 varLambda 参数可用 var无兼容性问题
 API字符串新方法isBlanklinesstriprepeat仅 JDK 11+ 可用,低版本需兼容处理
 平台移除 Java EE / CORBA 模块删除旧 API 模块高影响:依赖需改用 Jakarta EE 等替代方案
JDK 12语言Switch 表达式(预览)switch 返回值、-> 语法预览特性,需 --enable-preview
 JVMShenandoah GC(实验)低延迟 GC低延迟需求可考虑启用
 JVMG1 改进提升混合回收性能无兼容性问题
JDK 13语言文本块(预览)""" 多行字符串预览特性,减少转义
 JVMZGC 改进释放未使用内存大堆内存场景有益
JDK 14语言Record(预览)不可变数据类预览特性,适合 DTO/VO
 语言instanceof 模式匹配(预览)自动强转变量预览特性,简化代码
 JVMNullPointerException 精确消息NPE 提示变量名排查更方便
 语言Switch 表达式(正式)从预览转标准无需预览参数
JDK 15语言密封类(Sealed Class,预览)限制继承类范围预览特性,需 permits
 语言文本块(正式)三引号多行字符串无兼容性问题
 JVMZGC/G1 类卸载支持类卸载能力增强内存释放更积极
 JVM隐藏类(Hidden Class)动态生成类支持框架可用
JDK 16语言Record(正式)不可变数据类标准化可用于 DTO/值对象
 语言instanceof 模式匹配(正式)自动强转代码更简洁
 APIVector API(孵化)SIMD 加速高性能计算可用
 APIUnix Domain Socket原生支持 Unix 域套接字跨进程通信可用
JDK 17语言密封类(正式)限制继承范围标准化适合安全约束模型
 语言switch 模式匹配(预览)switch 支持类型模式匹配预览特性,需开启
 平台JDK 内部 API 强封装内部 API 默认不可访问高影响:反射访问需迁移至公开 API
 平台新 macOS 渲染管线基于 MetalmacOS 上图形渲染性能提升
 API外部函数与内存 API(孵化)替代 JNI 的新 API高性能原生调用可用
 平台删除 RMI Activation 系统移除过时 RMI 模块若使用需迁移至自定义方案

 

模块化系统

JDK 的 模块化系统(Java Platform Module System, JPMS) 是在 JDK 9 引入的,核心目标是让 JDK 自身模块化,同时为应用提供更清晰的依赖隔离与打包能力。
这不仅是语言/平台的一次重大演进,还直接改变了 JDK 结构(JDK 8 以前的 rt.jar、tools.jar 都没了)。


1. 模块化的核心概念

概念说明示例
module模块是包的集合,并声明依赖和导出module java.sql { exports java.sql; requires java.base; }
module-info.java模块描述文件,位于模块根目录,用来声明模块的依赖和导出见下方示例
exports声明对外暴露的包(默认不导出)exports com.example.utils;
requires声明依赖的模块(默认不隐式引入)requires java.sql;
opens运行时对反射开放(不影响编译期封装)opens com.example.model to gson;
provides / usesSPI 服务声明与消费provides MyService with MyServiceImpl;

 


2. 模块化打包与依赖隔离

2.1 模块化打包

  • 传统 JAR → 模块化 JAR(包含 module-info.class

  • 打包后可使用 jlink 按需生成运行时(只包含应用需要的 JDK 模块)

  • 命令示例

javac -d out/com.example.module src/module-info.java src/com/example/**/*.java jar --create --file com.example.module.jar -C out/com.example.module .

2.2 依赖隔离机制

  • 模块之间默认互不可见,必须通过 requires 明确声明依赖

  • exports 的包无法被外部访问(编译期直接报错)

  • 优势

    1. 防止依赖“污染” → 避免 Classpath Hell

    2. 运行时启动更快(按需加载模块)

    3. 减少打包体积(jlink 剪裁)


3. module-info.java 示例

module com.example.app {requires java.sql;             // 编译期依赖 java.sql 模块requires com.example.utils;    // 依赖自定义工具模块exports com.example.app.api;   // 暴露 API 包opens com.example.app.model to gson; // 对 gson 库开放反射访问uses com.example.spi.MyService;     // 消费服务接口provides com.example.spi.MyService with com.example.impl.MyServiceImpl; // 提供实现
}

4. 迁移时的注意点

  • 内部 API 强封装(见你上一个问题),很多 JDK 内部包需要通过 --add-exports / --add-opens 临时开放,否则编译或运行失败

  • 一些第三方库(尤其是老版本)会因为反射访问被阻止而报错

  • 打包工具(如 Maven Shade、Spring Boot fat jar)在 JPMS 下要重新配置

  • 动态模块路径(--module-path)与传统 classpath 是不同的加载机制


5. 可选迁移策略

场景建议
老项目,依赖很多反射/内部 API先用 --illegal-access=permit 兼容运行,逐步改代码
新项目直接用 JPMS,按需暴露包,依赖显式声明
想减小部署体积配合 jlink 定制 JRE
使用 Spring Boot 等框架注意部分框架(如 Hibernate)需要 opens 才能工作

 


应用类数据共享

应用类数据共享(AppCDS,Application Class-Data Sharing)是 JDK 10 起正式引入(早期 JDK 5 就有基础的 CDS 功能),在 JDK 12 之后进一步增强的 JVM 特性,主要用于 加快 JVM 启动速度、减少内存占用


1. 背景与原理

  • CDS(Class Data Sharing) 最初只针对 JDK 自带的系统类rt.jarjava.base 等模块里的类),将它们的元数据(metadata)提前解析好,存入共享归档文件(archive file)。

  • AppCDS 将这个机制扩展到 用户应用的类,即可以让你自己写的类也享受“提前解析+共享加载”的好处。

  • 归档文件里存的不是 .class 字节码,而是经过 类加载、链接(linking)后 JVM 内部结构(klass metadata、常量池等),因此 JVM 启动时直接映射到内存,不必重复解析字节码

好处:

  1. 启动速度提升

    • 省掉类加载 & 验证 & 解析元数据的时间。

  2. 内存占用降低

    • 多个 JVM 实例可以共享同一份类元数据映射(内存映射文件),不必各自保存一份。


2. 版本演进

JDK 版本特性变化
JDK 5首次引入 CDS(仅系统类)
JDK 9模块化后,CDS 支持模块归档
JDK 10AppCDS 引入,支持用户类归档,但需要手动两步生成(dump → use)
JDK 12AppCDS 归档文件生成命令简化,支持动态归档(无需 -Xshare:dump 单独跑一次)
JDK 13+自动支持 default CDS archive(开箱即用)
JDK 17AppCDS 稳定,支持容器环境(与 G1、ZGC 等配合)

 


3. 使用方法(以 JDK 17 为例)

3.1 生成归档

两种方式:

方式 1:两步生成

# 1. 运行应用生成类列表

java -Xshare:off -XX:DumpLoadedClassList=classes.lst -cp app.jar com.example.Main

 

# 2. 根据类列表生成共享归档

java -Xshare:dump \ -XX:SharedClassListFile=classes.lst \ -XX:SharedArchiveFile=appcds.jsa \ -cp app.jar

方式 2:一键生成(JDK 12+ 动态 CDS)

java -XX:ArchiveClassesAtExit=appcds.jsa -cp app.jar com.example.Main 

运行结束后会生成 appcds.jsa 文件。


3.2 使用归档

java -Xshare:on -XX:SharedArchiveFile=appcds.jsa -cp app.jar com.example.Main


4. 限制与注意事项

  1. 类路径 / 模块路径 要一致

    • AppCDS 归档和运行时 classpath/modulepath 必须匹配,否则 JVM 会忽略不兼容的类。

  2. 归档不可移植

    • 归档文件和生成它的 JVM 版本、OS、架构绑定(不能跨平台或跨不同 JDK 版本用)。

  3. 仅共享类元数据,不共享字节码

    • 方法字节码依然需要 JIT 编译,AppCDS 主要优化启动和内存占用。

  4. 动态类加载除外

    • 如反射生成的类、运行时生成代理类等不会进入归档。


5. 最佳实践(迁移建议)

  • 建议场景

    • 微服务 / Serverless 场景(频繁启动)

    • 多 JVM 实例并行运行(容器集群)

    • 冷启动性能敏感的 CLI 工具

  • 优化建议

    1. 在 CI/CD 里加一个 AppCDS 构建阶段,生成归档文件随应用一同部署。

    2. 对 classpath 做版本锁定,避免启动时因为 jar 版本变动导致归档失效。

    3. 配合 G1GCZGC 等现代 GC 使用,最大化启动 & 内存收益。

 

http://www.dtcms.com/a/328160.html

相关文章:

  • 【154页PPT】某大型再生资源集团管控企业数字化转型SAP解决方案(附下载方式)
  • 麒麟信安“操作系统+云”双驱动,推进某市公安局智慧警务建设
  • 云部署 MCP 服务计费
  • Java 包
  • 飞算JavaAI:Java智能开发工具的技术解析、应用实践
  • 燕山大学计算机网络实验(2025最新)
  • Python科学计算与可视化领域工具TVTK、Mayavi、Mlab、Traits(附视频教程)
  • 【AI】Pycharm中要注意Python程序文件的位置
  • 【C#】正则表达式
  • Lyapunov与SAC算法的数学结构对比:从二次漂移到TD损失
  • 【KO】Android Framework
  • 串口超时参数深度解析:ReadTotalTimeoutMultiplier、ReadIntervalTimeout等
  • 熟悉并使用Spring框架 - 注解篇
  • JavaWeb从入门到精通!第二天!(Servlet)
  • Jenkins + SonarQube 从原理到实战三:SonarQube 打通 Windows AD(LDAP)认证与踩坑记录
  • 基于多模态大模型的个性化学习路径生成系统研究
  • 循环神经网络(RNN)全面解析
  • 运维学习Day22——Anisible自动化与基本使用
  • SpringBoot面试宝典
  • MySQL User表入门教程
  • Spyglass CDC rule
  • NLP—词向量转换评论学习项目分析
  • 28.分类算法:让机器学会分类
  • Tauri Qt孰优孰劣
  • ncurses 6.5 交叉编译移植到OpenHarmomy
  • 2025年渗透测试面试题总结-16(题目+回答)
  • Linux文件系统:从虚拟接口到物理实现的架构解析
  • 【C#】用队列构建一个对象池管理对象的创建和释放
  • NumPy 快速入门与实战教程(逐行拆解 + 专业扩展)
  • 详细了解sklearn中的CountVectorizer