You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

构建时生成Java CDS类列表 避免K8s Pod重启及归档错误

构建时手动生成Java CDS类列表跳过K8s Pod重启的问题解决

问题背景

你在Kubernetes部署的Java应用中使用CDS归档优化启动速度,之前通过修改Java opts(-XX:+ArchiveClassesAtExit)生成类列表并创建归档,成功节省约60秒启动时间。现在希望在构建阶段手动生成类列表,避免生成类列表所需的Pod重启步骤,但遍历项目所有Jar生成类列表后,创建归档时出现以下错误:

[error][cds,heap] Cannot archive the sub-graph referenced from [Ljava.util.concurrent.ConcurrentHashMap$Node; object (0x00000000ad07fd00) size 1048592, skipped.
[error][cds] An error has occurred while writing the shared archive file.

报错原因

手动遍历Jar生成的类列表包含了不适合CDS归档的类/对象引用:

  • [Ljava.util.concurrent.ConcurrentHashMap$Node;是ConcurrentHashMap的内部数组类,属于运行时动态创建的大对象,CDS无法归档这类对象的引用子图。
  • Jar中存在大量启动阶段不会加载的类,手动全量收集的列表包含了这些类,导致JVM在归档时尝试处理无法被归档的运行时对象。

可行解决方案

1. 优化手动类列表生成逻辑,只收集启动阶段加载的类

  • 先通过JVM启动日志筛选实际加载的类:添加-verbose:class参数启动应用,输出所有加载的类,以此为基础生成类列表,剔除运行时动态创建的数组类(如[Lxxx;格式的类名)。
  • 用工具分析启动类加载:比如jcmd <pid> VM.class_hierarchy或Java Flight Recorder,捕获启动阶段的类加载数据,生成精准的类列表。

2. 构建阶段模拟启动生成归档(推荐)

不用手动遍历Jar,直接在CI/CD构建阶段启动一次应用生成归档,既避免生产Pod重启,又保证类列表的准确性:

# 在构建容器中启动应用,指定生成归档文件
java -XX:+ArchiveClassesAtExit -XX:SharedArchiveFile=app-cds.jsa -jar your-app.jar &

# 等待应用启动完成(可通过curl检测健康接口替代sleep)
sleep 30

# 停止应用,此时归档文件已生成
pkill -f your-app.jar

# 将归档文件打包到最终镜像的指定路径(比如/opt/app/)

这种方式由JVM自主筛选适合归档的类,不会包含无法归档的大对象引用,可靠性远高于手动遍历。

3. 调整CDS参数跳过无法归档的对象

如果坚持手动生成类列表,可添加参数让JVM跳过报错的对象:

java -XX:SharedArchiveFile=your-archive.jsa -XX:+UseSharedSpaces -XX:SkipUnsupportedClassesInArchive=true -jar your-app.jar

但此方法可能损失部分CDS优化效果,需测试验证启动速度变化。

内容的提问来源于stack exchange,提问作者curious_lak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 20:12:33