Java调用LMDB API执行Env.create()时报java.nio访问权限错误如何解决
问题原因
这个报错是Java 9及以上版本引入的JPMS(Java平台模块系统)限制导致的:lmdbjava底层默认通过反射读取java.nio.Buffer类的address私有字段实现高性能IO,而高版本Java默认禁止未声明权限的反射访问JDK内部模块的成员。
解决方案
方案1:添加JVM启动参数(最快适配,性能无损失)
在你的Java程序启动参数中添加如下配置即可:
--add-opens java.base/java.nio=ALL-UNNAMED
- 如果你用IDEA/Eclipse等IDE运行,直接在对应运行配置的「VM选项」栏输入上述参数
- 如果你用命令行运行,指令格式为:
java --add-opens java.base/java.nio=ALL-UNNAMED 你的主类全限定名
如果你是模块化项目(项目根目录存在module-info.java),在module-info.java中添加如下声明即可,不需要加启动参数:
opens java.nio to org.lmdbjava;
方案2:使用安全代理实现(无需改启动参数,兼容所有Java版本)
创建Env实例时指定使用无反射的安全代理即可,仅性能相比反射实现略有下降:
把你代码里的
dbEnvironment = Env.create().setMapSize(1_073_741_824).setMaxDbs(1).open(dbDirectory);
改成
// 先判断目录不存在就创建,避免后续打开报错 if (!dbDirectory.exists()) { dbDirectory.mkdirs(); } dbEnvironment = Env.create(ByteBufferProxy.PROXY_SAFE) .setMapSize(1_073_741_824) .setMaxDbs(1) .open(dbDirectory);
额外注意点
你当前的代码没有判断数据存储目录是否存在,lmdb的open方法不会自动创建父目录,若./data目录不存在会额外触发目录不存在的报错,建议添加上面代码里的目录创建逻辑。
内容的提问来源于stack exchange,提问作者Vishnu Chithan
相关产品推荐
相关产品推荐

