jlink打包应用中使用Java 14预览特性Records抛出异常
解决jlink打包Java 14预览Records时的ClassFormatError问题
这个错误是因为你使用的--strip-debug选项和Java 14的预览特性Records存在兼容性问题——当剥离调试信息时,jlink会移除类文件常量池中的某些条目,而Record属性的结构依赖这些条目来解析名称,最终导致类加载时出现Invalid constant pool index错误。
快速解决方案
你有两种可行的调整方式:
- 暂时移除
--strip-debug选项
直接修改jlink配置,去掉会引发冲突的选项:
options = ['--compress', '2', '--no-header-files', '--no-man-pages']
- 编译阶段提前剥离调试信息
如果确实需要缩减包体积,建议在编译时就用javac的-g:none选项去掉调试信息,而非依赖jlink的--strip-debug:
- 编译命令添加参数:
javac --enable-preview -source 14 -g:none your-source-files.java
- 之后再用你原来的jlink选项打包即可:
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
深层原因解释
Java 14的Records作为预览特性,其类文件中的Record属性在存储名称信息时,依赖于常量池中的调试相关条目。jlink的--strip-debug操作会粗暴地移除这些常量池条目,但并没有同步更新Record属性中对应的索引值,导致类加载器在解析Record类时找不到正确的常量池位置,从而抛出ClassFormatError。
而javac -g:none是在编译阶段就不生成调试信息,类文件的Record属性会基于编译后的常量池结构正确生成,后续jlink的--strip-debug就不会破坏已有的索引关联了。
内容的提问来源于stack exchange,提问作者Aksel Willgert
相关产品推荐
相关产品推荐

