如何在Quarkus中使用JNI?@QuarkusTest本地库加载失败求助
解决QuarkusTest中加载本地JNI库的UnsatisfiedLinkError问题
问题背景
本地库编译后位于项目target目录(Windows为MyLib.dll,Linux为MyLib.so),普通单元测试通过System.loadLibrary("MyLib")可正常使用,但在@QuarkusTest中抛出java.lang.UnsatisfiedLinkError: 'long org.acme.xxx.new_ObjectInMyLib()'错误。
解决方案
1. 正确配置Quarkus的JNI库路径
在测试环境配置文件(src/test/resources/application-test.properties)中添加:
# 直接指向target目录,跨平台自动适配 quarkus.jni.library-paths=${project.build.directory}
无需额外添加quarkus-core-deployment依赖,quarkus-core已包含JNI支持。
2. 手动加载库并刷新系统库路径(配置不生效时备用)
如果自动配置仍不生效,可在测试类启动前手动设置java.library.path并刷新JVM的库路径缓存:
import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.BeforeAll; import java.io.File; import java.lang.reflect.Field; @QuarkusTest public class MyLibIntegrationTest { @BeforeAll static void initializeNativeLibrary() { // 获取target目录的绝对路径 String targetDir = new File(System.getProperty("project.build.directory")).getAbsolutePath(); // 更新java.library.path System.setProperty("java.library.path", targetDir); // 反射重置ClassLoader的sys_paths,触发JVM重新扫描库路径 try { Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths"); sysPathsField.setAccessible(true); sysPathsField.set(null, null); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException("Failed to refresh JVM library path", e); } // 加载本地库 System.loadLibrary("MyLib"); } // 测试用例... }
3. 排查其他可能原因
- 架构匹配:确保本地库的CPU架构(x86/amd64)与运行测试的JVM架构一致;
- JNI签名一致性:用
javah工具重新生成JNI头文件,确认Java方法的全限定名、参数/返回类型与本地库实现完全匹配; - DevServices影响:如果启用了Quarkus DevServices(如容器化测试),需确保容器内环境能访问到本地库(可将库挂载到容器中)。
内容的提问来源于stack exchange,提问作者Morlin
相关产品推荐
相关产品推荐

