精简JRE运行PDFBOX 3.0.1遇Loader异常:缺失哪个模块?
问题背景
使用PDFBox 3.0.1时,在通过jlink构建的精简JRE中触发java.lang.ExceptionInInitializerError(报错栈指向org.apache.pdfbox.Loader.loadPDF(Loader.java:369)),但该程序在完整OpenJDK 11/17、Oracle JRE 8中运行正常。添加jdk.unsupported模块可修复问题,但会大幅增加JRE体积;通过类加载日志发现,正常运行时会加载sun.misc.Unsafe,异常场景下则不会,推测问题与commons-io 2.15.1的IOUtils依赖sun.misc.Unsafe有关。
解决建议
1. 升级commons-io版本(优先推荐)
commons-io从2.16.0版本开始,已移除对sun.misc.Unsafe的依赖,改用Java标准API实现相关功能。将项目中的commons-io依赖升级至2.16.0或更高版本后,无需添加jdk.unsupported模块,即可让PDFBox在精简JRE中正常运行,同时保持JRE体积精简。
2. 手动暴露Unsafe相关包(无法升级依赖时)
如果暂时无法升级commons-io,可通过jlink的--add-exports和--add-opens参数,仅暴露sun.misc包给未命名模块,而非引入整个jdk.unsupported模块。修改后的jlink命令如下:
.\jlink --output jre-17.0.6 --compress=2 --no-header-files --no-man-pages --module-path ../jmods --add-modules java.base,java.compiler,java.datatransfer,java.desktop,java.instrument,java.logging,java.management,java.management.rmi,java.naming,java.net.http,java.prefs,java.rmi,java.scripting,java.se,java.security.jgss,java.security.sasl,java.smartcardio,java.sql,java.sql.rowset,java.transaction.xa,java.xml,java.xml.crypto,jdk.localedata,jdk.crypto.ec --add-exports java.base/sun.misc=ALL-UNNAMED --add-opens java.base/sun.misc=ALL-UNNAMED
这种方式既能满足PDFBox/commons-io对sun.misc.Unsafe的需求,又能避免引入jdk.unsupported模块的冗余内容,有效控制精简JRE的体积。
3. 调整代码使用PDFBox原生IO工具
尝试替换自定义的IO逻辑,直接使用PDFBox提供的IO工具类(如优化RandomAccessRead的使用方式),避免间接触发commons-io中依赖Unsafe的代码路径。不过此方式需要调整业务代码,适合对代码可控性较高的场景。
内容的提问来源于stack exchange,提问作者mediocre man

