登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  java教程

Java CDS 怎样缩短应用启动时间

来源:17golang原创

时间:2026-11-02 11:14:42 112浏览 收藏

Java CDS(Class Data Sharing)缩短启动时间的关键,不是把 Java 程序提前编译成另一种语言,而是让多个 JVM 复用已经整理好的类元数据。Oracle JDK 默认会尝试使用 CDS 归档;如果应用启动还要加载大量固定的业务类,可以再制作 AppCDS 动态归档,把应用类也纳入复用范围。

官方地址:https://docs.oracle.com/en/java/javase/24/vm/class-data-sharing.html

最小落地路径是:先保持生产启动命令不变运行一次,用 -XX:ArchiveClassesAtExit 生成动态归档;再用同一套 JDK、类路径和启动参数,通过 -XX:SharedArchiveFile 加载它。归档是启动优化的补充,不能替代应用本身的初始化治理。

先分清默认 CDS 和 AppCDS

默认 CDS 主要覆盖 JDK 核心类。JVM 启动时可以把归档中的只读元数据映射进进程,让多个 JVM 共享这部分内容;从 JDK 12 起,Oracle JDK 二进制通常会预置默认 CDS 归档。默认功能已经启用时,不需要先写一套复杂脚本。

当应用相对较小、但每次启动都要重复加载相同的业务类时,AppCDS 才更值得考虑。它把应用类路径中的选定类纳入归档,适合启动命令、依赖版本和运行方式都比较稳定的服务。

Java CDS 默认归档、应用类路径和 AppCDS 动态归档关系的静态说明图
图1:结构说明图展示默认 CDS、应用类与 AppCDS 动态归档的静态关系,不是运行截图。

用一次试运行生成动态归档

动态归档的优点是步骤更少,通常也不必重复保存默认归档已经覆盖的类。下面假设应用由固定的 app.jar 启动,先用与生产一致的命令跑一遍,让 JVM 记录这次实际加载到的类:

# 用与生产一致的类路径运行一次,并在退出时写出动态 CDS 归档
java -XX:ArchiveClassesAtExit=app.jsa -jar app.jar

这里的 app.jsa 是归档文件名,实际部署时应放到稳定的发布目录。试运行覆盖到的代码路径越接近真实启动路径,归档越有机会覆盖稳定的启动类;但它不是把所有未来可能加载的类都预先收集进去。

如果应用的启动器很复杂,也可以让正在运行的 JVM 先以 -XX:+RecordDynamicDumpInfo 启动,再通过 jcmd 连接进程创建动态归档:

# 让 JVM 记录动态归档所需的信息;pid 替换为目标 Java 进程号
java -XX:+RecordDynamicDumpInfo -jar app.jar

# 从运行中的 JVM 导出动态归档,不改写应用自身的启动参数
jcmd  VM.cds dynamic_dump app.jsa

两种方式都依赖真实的应用启动路径。不要为了“让归档更大”而随意扩大类路径,归档内容应服务于稳定的启动场景。

让后续 JVM 加载应用归档

生成归档后,后续启动命令增加 -XX:SharedArchiveFile:

# 使用动态归档启动同一个应用;类路径和 JDK 要与创建归档时保持一致
java -XX:SharedArchiveFile=app.jsa -jar app.jar

如果同时维护静态归档与动态归档,可以用平台对应的路径分隔符组合它们。Oracle 文档说明,静态归档先加载,动态归档再叠加;在 Windows 上,示例中的冒号需要换成分号:

# Linux/macOS 示例:先加载基础归档,再加载应用动态归档
java -XX:SharedArchiveFile=base.jsa:app.jsa -jar app.jar

生产上最重要的变化不是多加一个 JVM 参数,而是把归档文件和启动命令绑定到同一次发布。应用 JAR、依赖目录或启动参数变化后,应重新生成归档,而不是继续沿用旧文件。

归档为什么会失效

CDS 归档不是跨环境通用缓存。归档内容与创建它的 JDK 构建相关;类路径中的 JAR 被修改、运行时类路径与创建时不一致,或者模块相关参数变化,都可能让归档无法加载、只部分生效,甚至被禁用。

还要注意三个常见边界:带非空目录的类路径或模块路径不符合 CDS 的限制;--upgrade-module-path、--patch-module 和 --limit-modules 会禁用 CDS;-Xshare:on 适合测试归档是否能用,但官方不建议把它作为生产参数,因为归档不可用时 JVM 可能直接退出。

Java CDS 归档与 JDK 构建、类路径、模块参数依赖的边界说明图
图2:边界说明图展示 CDS 归档与 JDK 构建、类路径、模块参数和加载命令的静态依赖,不是性能验证结果。

根据发布方式选择归档方案

场景优先方案原因
只想获得基础收益保留默认 CDSJVM 默认尝试加载核心类归档,改动最小
启动命令和依赖稳定ArchiveClassesAtExit + SharedArchiveFile能把应用启动类纳入动态归档,步骤清晰
启动脚本复杂但 JVM 可持续运行jcmd VM.cds dynamic_dump减少对启动脚本的侵入
希望按相同命令自动维护-XX:+AutoCreateSharedArchiveJDK 19 及之后可按归档文件和 JDK 版本自动创建或重建

最后不要只看单次启动耗时就宣布优化完成。至少要把归档文件作为构建产物管理,并在 JDK、依赖、类路径或模块参数变更时重新生成;如果归档被忽略,先检查启动条件是否一致,再决定是否继续保留这个参数。

相关问题

  • Java CDS 默认需要手动打开吗?通常不需要,默认模式会在可用时尝试使用 CDS;可用 -Xshare:off 关闭。
  • AppCDS 能不能替代 JIT 优化?不能。CDS 主要减少类加载和元数据准备成本,不等于提前完成运行期 JIT 编译。
  • 换了 JDK 还能继续用旧的 jsa 吗?不要直接假设可以。归档与 JDK 构建绑定,换 JDK 或关键启动条件后应重新生成并重新评估。
声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>