如何为db4o模块开放classes包?Java模块权限报错解决
解决db4o跨模块反射访问权限错误
我在使用db4o执行简单的增、查数据操作时,触发了以下错误:
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private int classes.Professor.id accessible: module recuperacio does not "opens classes" to module db4o at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:388) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:364) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:312) at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:183) at java.base/java.lang.reflect.Field.setAccessible(Field.java:177) at db4o@8.0.249.16098-all-java5/com.db4o.internal.JDK_1_2.setAccessible(JDK_1_2.java:122) at db4o@8.0.249.16098-all-java5/com.db4o.internal.Platform4.setAccessible(Platform4.java:526) at db4o@8.0.249.16098-all-java5/com.db4o.reflect.jdk.JdkField.setAccessible(JdkField.java:48) at db4o@8.0.249.16098-all-java5/com.db4o.reflect.jdk.JdkField.<init>(JdkField.java:24) at db4o@8.0.249.16098-all-java5/com.db4o.reflect.jdk.JdkClass.createField(JdkClass.java:71) at db4o@8.0.249.16098-all-java5/com.db4o.reflect.jdk.JdkClass.getDeclaredFields(JdkClass.java:79) at db4o@8.0.249.16098-all-java5/com.db4o.reflect.generic.GenericClass.getDeclaredFields(GenericClass.java:106) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ClassMetadata.reflectFields(ClassMetadata.java:1824) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ClassMetadata.collectReflectFields(ClassMetadata.java:394) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ClassMetadata.initializeAspects(ClassMetadata.java:240) at db4o@8.0.249.16098-all-java5/com.db4o.internal.PendingClassInits.initializeAspects(PendingClassInits.java:56) at db4o@8.0.249.16098-all-java5/com.db4o.internal.PendingClassInits.checkStatics(PendingClassInits.java:62) at db4o@8.0.249.16098-all-java5/com.db4o.internal.PendingClassInits.checkWrites(PendingClassInits.java:72) at db4o@8.0.249.16098-all-java5/com.db4o.internal.PendingClassInits.checkInits(PendingClassInits.java:83) at db4o@8.0.249.16098-all-java5/com.db4o.internal.PendingClassInits.process(PendingClassInits.java:45) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ClassMetadataRepository.produceClassMetadata(ClassMetadataRepository.java:233) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase.produceClassMetadata(ObjectContainerBase.java:1019) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectAnalyzer.detectClassMetadata(ObjectAnalyzer.java:58) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectAnalyzer.analyze(ObjectAnalyzer.java:40) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase.store2(ObjectContainerBase.java:1675) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase.storeAfterReplication(ObjectContainerBase.java:1618) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase$10.apply(ObjectContainerBase.java:1604) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase$10.apply(ObjectContainerBase.java:1602) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase.asTopLevelCall(ObjectContainerBase.java:427) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase.asTopLevelStore(ObjectContainerBase.java:413) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase.storeInternal(ObjectContainerBase.java:1602) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ObjectContainerBase.store(ObjectContainerBase.java:1584) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ExternalObjectContainer.store(ExternalObjectContainer.java:129) at db4o@8.0.249.16098-all-java5/com.db4o.internal.ExternalObjectContainer.store(ExternalObjectContainer.java:124) at recuperacio/db.newdb4o.prova(newdb4o.java:26) at recuperacio/main.main2.main(main2.java:12)
已知需要开放类的访问权限,但不清楚具体操作方式和位置,项目核心代码如下:
package db; import java.io.File; import com.db4o.Db4o; import com.db4o.Db4oEmbedded; import com.db4o.ObjectContainer; import com.db4o.ObjectSet; import com.db4o.config.EmbeddedConfiguration; import classes.Professor; public class newdb4o { private ObjectContainer db; public newdb4o() { super(); String DB4OFILENAME ="taula.db4o" ; new File(DB4OFILENAME).delete(); EmbeddedConfiguration config = Db4oEmbedded.newConfiguration(); ObjectContainer db = Db4oEmbedded.openFile(config,DB4OFILENAME); this.db = db; } public void prova() { Professor testteacher1 = new Professor(1, "test1", 5); db.store(testteacher1); } public void test2() { Professor testteacher1 = new Professor(1, null, 0); ObjectSet result =db.queryByExample(testteacher1); System.out.print(result); } }
解决方法
1. 通过模块声明文件配置权限
在你的recuperacio模块根目录下创建module-info.java文件(路径:src/main/java/module-info.java),添加以下内容:
module recuperacio { // 开放classes包给db4o模块,允许其反射访问包内类的私有成员 opens classes to db4o; // 声明依赖db4o模块 requires db4o; }
这是Java模块系统的标准做法,能长期稳定解决权限问题。
2. 通过JVM启动参数临时开放权限
如果不想修改模块配置,可以在启动程序时添加VM参数,强制开放指定包的反射访问权限:
--add-opens recuperacio/classes=db4o
- IDE运行:在运行配置的「VM options」中添加该参数
- 命令行运行:
java --add-opens recuperacio/classes=db4o -jar 你的应用.jar
这种方式适合临时调试场景,不推荐用于生产环境。
补充说明
db4o依赖反射访问实体类的私有字段(如Professor.id)来完成对象的持久化和查询,而Java 9+引入的模块系统默认禁止跨模块的反射访问,因此必须显式开放对应包或模块的权限。
如果不想修改模块或启动参数,也可以将Professor类的字段改为public,或者添加对应的getter/setter方法,但这会破坏类的封装性,不是最优方案。
内容的提问来源于stack exchange,提问作者Drex
相关产品推荐
相关产品推荐

