上一篇
Java怎么调用so库?
- 后端开发
- 2025-07-03
- 5
在Java中调用SO库需使用 JNI技术:首先声明native方法,编译生成头文件;用C/C++实现函数并编译为SO文件;最后通过System.loadLibrary加载SO库,即可调用本地方法实现跨语言交互。
在Java中调用共享库(.so文件)是通过Java本地接口(JNI)或第三方库(如JNA)实现的,主要用于执行高性能计算、硬件操作或复用C/C++代码,以下是详细步骤和注意事项:
核心方法:JNI 与 JNA
JNI(Java Native Interface)
步骤:
-
编写Java类声明Native方法
-
生成C/C++头文件
使用javac -h生成头文件:
javac NativeLib.java -h ./headers生成的头文件(NativeLib.h)包含函数签名:
JNIEXPORT void JNICALL Java_NativeLib_printMessage(JNIEnv *, jobject);
-
实现C/C++代码
#include <stdio.h> #include "headers/NativeLib.h" JNIEXPORT void JNICALL Java_NativeLib_printMessage(JNIEnv *env, jobject obj) { printf("Hello from C via JNI!n"); } -
编译生成.so文件
使用GCC编译:
gcc -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -shared -fpic -o libmylib.so NativeLib.c
-
运行Java程序
确保.so文件在java.library.path中:
java -Djava.library.path=/path/to/so/dir NativeLib -
添加JNA依赖(Maven)
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.13.0</version> </dependency> -
定义接口映射C函数
import com.sun.jna.Library; import com.sun.jna.Native; public class JnaExample { public interface MyLib extends Library { MyLib INSTANCE = Native.load("mylib", MyLib.class); void printMessage(); // 映射C函数 } public static void main(String[] args) { MyLib.INSTANCE.printMessage(); } } -
直接运行
无需生成头文件或编译Java代码,JNA自动处理绑定。
-
路径问题

- 将.so文件放在/usr/lib或LD_LIBRARY_PATH包含的目录。
- 或通过启动参数指定: java -Djava.library.path=/custom/path ...
-
ABI兼容性
- 确保.so文件的架构(x86/ARM)与JVM一致。
- 使用file libmylib.so检查文件格式。
-
版本管理
- 避免库冲突:不同版本的.so文件分开存放。
- 通过System.mapLibraryName("mylib")获取系统特定名称(如libmylib.so)。
-
安全性
- 验证外部库来源,防止恶意代码载入。
- 限制Native方法的权限(如使用SecurityManager)。
-
错误排查
- UnsatisfiedLinkError:检查路径、函数名拼写、库依赖(ldd libmylib.so)。
- 使用nm -D libmylib.so | grep printMessage验证函数是否导出。
- 封装Native调用
将JNI/JNA逻辑隔离在独立类中,避免业务代码耦合。
- 资源释放
在Native代码中及时释放内存(如free),防止内存泄漏。
- 跨平台处理
使用条件加载: String libName = System.getProperty("os.name").startsWith("Linux") ? "mylib" : "mylib.dll"; System.loadLibrary(libName);
- Oracle JNI官方文档:JNI开发权威指南。
- JNA GitHub仓库:JNA源码及示例。
- 《Java性能权威指南》(O’Reilly):Native调用的优化建议。
适用场景对比
方法 优点 缺点 JNI 高性能、官方标准 步骤繁琐、需编译C代码 JNA 无需编译、简单易用 性能略低、依赖第三方库
最佳实践
引用说明
通过遵循上述步骤和注意事项,可安全高效地在Java中调用.so库,兼顾性能与可维护性,建议优先使用JNA简化开发,对性能有极致要求时选择JNI。

JNA(Java Native Access)
步骤:
关键注意事项