模块化环境下Hibernate运行失败问题排查与求助
问题背景
正将基于javax JPA的旧工具迁移至Jakarta版本的新版Hibernate,在模块化项目中运行时遇到问题:实例化HibernatePersistenceProvider类时触发ExceptionInInitializerError,根源为JBoss Logging的模块访问问题。
已搭建MCVE复现问题:使用Gradle 8.10.2与Java 23,配置相关依赖与module-info.java后,运行测试出现两类核心错误:
- 使用JBoss Logging 3.6.1.Final时,提示无法访问
org.hibernate.internal.EntityManagerMessageLogger - 降级至3.5.0.Final时,出现
IllegalAccessError,提示org.jboss.logging模块未读取java.logging模块 - 降级Hibernate至6.6.1.Final也无法解决问题
移除module-info.java并注释gradle.build的doFirst块后问题消失,但无法放弃模块化,现求助以下问题:
- 是否需修改
module-info.java? - 是否需调整依赖版本?
- 是否需添加
--add-opens参数? - 是否不应直接实例化
HibernatePersistenceProvider? - 这是否是Hibernate的Bug?
简言之,哪里操作有误?该如何修复?
问题解答
1. 是否需修改module-info.java?
是,必须调整模块声明,确保你的模块正确依赖并开放必要权限:
module your.module.name { // 声明依赖核心模块 requires jakarta.persistence; requires org.hibernate.core; requires org.jboss.logging; // 开放你的持久化相关包,允许Hibernate和JBoss Logging反射访问 opens your.persistence.package to org.hibernate.core, org.jboss.logging; }
注意:org.hibernate.internal是Hibernate内部包,模块系统默认不对外暴露,不能直接依赖,需通过opens指令让框架能反射访问你的代码。
2. 是否需调整依赖版本?
是,必须保证Hibernate与JBoss Logging版本完全兼容:
- 不要手动指定JBoss Logging版本,使用Hibernate官方BOM统一管理依赖版本,避免版本冲突:
dependencies { implementation platform('org.hibernate.orm:hibernate-platform:6.7.2.Final') implementation 'org.hibernate.orm:hibernate-core' implementation 'jakarta.persistence:jakarta.persistence-api' }
Hibernate的BOM会自动引入适配当前版本的JBoss Logging,无需手动指定。
3. 是否需添加--add-opens参数?
可能需要,针对JDK内部包的访问限制:
JBoss Logging需要访问部分JDK内部类,需添加以下JVM启动参数:
--add-opens java.base/java.lang=org.jboss.logging --add-opens java.base/java.util=org.jboss.logging --add-opens java.logging/java.util.logging=org.jboss.logging
你的模块内部类的访问需求可通过module-info.java的opens指令解决,无需额外参数。
4. 是否不应直接实例化HibernatePersistenceProvider?
是,推荐使用Jakarta JPA标准API初始化,避免直接依赖Hibernate实现类:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("your-persistence-unit");
直接实例化HibernatePersistenceProvider会绕过JPA的模块化兼容层,容易触发访问权限问题,这也是Hibernate官方推荐的标准用法。
5. 是否是Hibernate的Bug?
大概率不是,主要是模块化配置不当导致的。但如果严格按照兼容版本和配置操作后仍有问题,可能是Hibernate 6.x对Java 23(非LTS版本)的适配不足,可尝试降级到Java 21(LTS版本)验证。
完整修复步骤
- 修正
module-info.java:添加必要的requires和opens指令,确保模块依赖与权限配置正确。 - 使用Hibernate BOM管理版本:移除手动指定的JBoss Logging版本,通过BOM统一控制依赖版本。
- 切换到JPA标准API:替换直接实例化
HibernatePersistenceProvider的代码,改用Persistence.createEntityManagerFactory。 - 添加JVM启动参数:配置
--add-opens参数,允许JBoss Logging访问JDK内部包。 - (可选)降级Java版本:若Java 23下问题仍存在,切换到Java 21 LTS版本测试。
内容的提问来源于stack exchange,提问作者Victor Stafusa

