Java 9/10无法运行Java 6编译的含DataNucleus 1.1.6的可执行Jar包
问题根源
我之前刚好处理过类似的问题,这本质是Java 9引入的模块系统(JPMS)和你用的老旧DataNucleus 1.1.6版本不兼容,导致JDO的服务发现机制失效了。
Java 6到8采用传统类路径的服务发现机制,JDO可以通过扫描Jar包中META-INF/services/javax.jdo.PersistenceManagerFactory文件找到对应的实现类。但Java 9及以上引入模块系统后,默认会限制这种无模块Jar的服务扫描行为,而DataNucleus 1.1.6完全是为Java 6设计的,根本没适配JPMS,所以才会抛出找不到PersistenceManagerFactory的错误。
可行解决方案
我整理了三个从易到难的方案,你可以根据自己的需求选择:
方案1:添加JVM兼容参数快速修复
这是最快的临时解决办法,不用改代码或依赖,只需要在启动Jar时添加几个JVM参数,强制Java 9+兼容旧的类路径服务发现机制:
- 首先确保所有DataNucleus相关依赖Jar(比如
datanucleus-core-1.1.6.jar、datanucleus-jdo-1.1.6.jar、jdo-api-xxx.jar)都在类路径中 - 启动命令示例:
java --add-modules java.se.ee --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED -jar 你的应用.jar
参数说明:
--add-modules java.se.ee:Java 9+默认未完全包含JDO相关的EE模块,这个参数把它们加回来--add-opens参数:解决旧版本DataNucleus使用反射访问Java核心类时的权限问题
方案2:升级DataNucleus到支持Java 9+的版本
如果你的应用打算长期在Java 9+环境运行,升级是最彻底的解决方案:
- 至少升级到DataNucleus 4.x及以上版本(比如4.0.0),这些版本已经适配了JPMS
- 注意:升级可能需要调整部分代码,因为新版本对应JDO 3.x API,和旧版本的JDO 2.x可能有一些API差异
- 确保所有DataNucleus组件(core、jdo、数据存储相关的模块)版本保持一致,避免版本冲突
方案3:手动指定PersistenceManagerFactory实现类
如果不想升级也不想加太多JVM参数,可以在你的JDO配置文件(比如jdo.properties或persistence.xml)中手动指定实现类:
- 添加配置项:
javax.jdo.PersistenceManagerFactoryClass = org.datanucleus.jdo.JDOPersistenceManagerFactory
- 这样JDO就会直接加载指定的类,不需要扫描服务文件,但可能还是需要配合方案1中的
--add-opens参数来解决反射权限问题
额外注意点
- 检查类路径是否完整:确保所有DataNucleus依赖Jar都被正确包含,Java 9+对类路径的可见性检查更严格
- 如果使用构建工具(Maven/Gradle),升级依赖时记得排除旧版本的冲突依赖
内容的提问来源于stack exchange,提问作者res1
相关产品推荐
相关产品推荐

