You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:24:54