Android JNI库适配Java SE遇UnsatisfiedLinkError,CMake构建失败求助
解决Java SE环境下JNI原生库构建与加载问题
错误原因
你碰到的UnsatisfiedLinkError核心是Java找不到对应的原生共享库——Android的Gradle插件会自动触发CMake构建流程,但标准Java SE的Gradle项目默认不会执行这一步,导致没有生成可供Java加载的库文件。
解决方案:两种方式实现构建与集成
方式一:手动用CMake构建原生库
先手动编译出Java SE兼容的共享库,再让Java加载:
- 创建并进入构建目录:
mkdir build && cd build - 执行CMake配置(不同平台可按需调整,比如Windows需指定生成器):
# macOS/Linux cmake .. -DCMAKE_BUILD_TYPE=Release # Windows示例(用VS2022生成器) cmake .. -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=Release - 编译生成库文件:
# macOS/Linux make -j4 # Windows cmake --build . --config Release - 找到编译后的库:
- macOS:
libutilities_whitebox.dylib - Linux:
libutilities_whitebox.so - Windows:
utilities_whitebox.dll
- macOS:
- 让Java定位到库:
- 方法1:把库文件放到错误提示里的
java.library.path路径(比如当前目录.) - 方法2:启动Java时指定库路径:
java -Djava.library.path=/你的库文件目录 MainClass
- 方法1:把库文件放到错误提示里的
方式二:用Gradle自动触发CMake构建
如果想通过Gradle统一管理Java编译和原生库构建,可在构建脚本中添加自定义任务:
Groovy版build.gradle配置
plugins { id 'java' } // 定义CMake构建任务 task buildNative(type: Exec) { def buildDir = file("$projectDir/build/native") buildDir.mkdirs() // 执行CMake配置 commandLine 'cmake', '..', '-DCMAKE_BUILD_TYPE=Release', "-B$buildDir" workingDir buildDir.parentFile // 执行编译 doLast { commandLine 'cmake', '--build', buildDir.path, '--config', 'Release' } } // 让Java编译任务依赖原生构建任务 compileJava.dependsOn buildNative // 配置Java运行时的库路径 run { systemProperty 'java.library.path', "$projectDir/build/native" }
Kotlin版build.gradle.kts配置
plugins { java } // 定义CMake构建任务 tasks.register<Exec>("buildNative") { val buildDir = file("$projectDir/build/native") buildDir.mkdirs() // CMake配置命令 commandLine("cmake", "..", "-DCMAKE_BUILD_TYPE=Release", "-B$buildDir") workingDir = buildDir.parentFile // 编译命令 doLast { commandLine("cmake", "--build", buildDir.path, "--config", "Release") } } // 让Java编译依赖原生构建 tasks.compileJava { dependsOn(tasks.named("buildNative")) } // 配置运行时库路径 tasks.run { systemProperty("java.library.path", "$projectDir/build/native") }
额外注意点
- 检查JNI桥接代码(
SwigWbc_wrap.cpp)是否兼容Java SE:如果代码里用到了Android专属JNI API(比如AndroidLog相关),需要替换成Java SE的实现。 - 不同平台的库文件格式不同,跨平台使用需分别编译对应版本。
内容的提问来源于stack exchange,提问作者Oyebisi
相关产品推荐
相关产品推荐

