Java调用C/C++需通过JNI,用System.loadLibrary("mylib")加载库(Linux找libmylib.so,Windows找mylib.dll),native方法须声明无实现,C函数名须为Java_com_example_Class_method,库须置于java.library.path指定路径。

在 Java 中调用本地 C/C++ 代码,需通过 JNI(Java Native Interface)机制,而 System.loadLibrary() 是最常用、推荐的加载方式。它不直接传入文件路径,而是根据库名自动查找并加载对应平台的动态链接库(如 Windows 的 .dll、Linux 的 .so、macOS 的 .dylib),前提是库已正确命名、放置在 JVM 能搜索到的路径中。
一、确保本地库符合 JNI 命名与导出规范
Java 查找的是“库名”而非完整文件名,且要求本地函数按 JNI 命名规则导出:
- 库文件名需带平台前缀和后缀:例如库名指定为
"mylib",则实际文件应为libmylib.so(Linux)、mylib.dll(Windows)、libmylib.dylib(macOS);Windows 下可省略lib前缀,但其他平台必须有。 - C/C++ 函数名须以
Java_开头,后接包名(用下划线_替代.)、类名、方法名。例如:public static native int add(int a, int b);在类com.example.NativeHelper中,则 C 函数应声明为:JNIEXPORT jint JNICALL Java_com_example_NativeHelper_add(JNIEnv *env, jclass cls, jint a, jint b) - 编译时需链接 JNI 头文件(
jni.h)和对应 JVM 的 native 库(如libjvm.so或jvm.lib),并导出符号(Linux/macOS 加-fPIC -shared,Windows 用/DLL)。
二、正确声明 native 方法并静态加载库
在 Java 类中,需先声明 native 方法,再在 static 块中调用 System.loadLibrary()。JVM 保证该调用只执行一次,且在类初始化时完成:
package com.example;
public class NativeHelper {
// 声明 native 方法(无方法体)
public static native int add(int a, int b);
// 静态块中加载库(库名不含前缀/后缀)
static {
System.loadLibrary("mylib"); // 加载 libmylib.so / mylib.dll 等
}
}
⚠️ 注意:库名必须与编译生成的文件名主体一致(去掉平台前缀和扩展名),且大小写敏感。
立即学习“Java免费学习笔记(深入)”;
三、将库文件放到 JVM 可搜索路径中
System.loadLibrary() 不接受路径,而是依赖 JVM 的库搜索逻辑。它会依次检查以下位置:
-
java.library.path系统属性指定的路径(默认包含java.home/lib、user.dir等) - 操作系统自身的动态库路径(如 Linux 的
LD_LIBRARY_PATH、Windows 的PATH、macOS 的DYLD_LIBRARY_PATH)
推荐做法是启动 Java 程序时显式指定路径:
java -Djava.library.path=/path/to/your/libs com.example.Main
或在代码中提前设置(需在任何 native 调用前):System.setProperty("java.library.path", "/path/to/your/libs");
但注意:修改该属性不会自动刷新 JVM 内部缓存,更可靠的方式仍是通过 JVM 启动参数传入。
四、常见错误与排查建议
-
UnsatisfiedLinkError: no xxx in java.library.path → 库文件名错误、未放入
java.library.path、或平台不匹配(如用 Linux 编译的.so运行在 Windows 上) -
UnsatisfiedLinkError: XXX method not found → C 函数签名不匹配(包名/类名/方法名拼写、参数类型、返回值类型不符),可用
nm -D libxxx.so(Linux)或otool -TV libxxx.dylib(macOS)检查导出符号 -
Access denied / Permission denied → Linux/macOS 下库文件缺少执行权限,运行
chmod +x libxxx.so - 避免混用
System.load()(需绝对路径)和loadLibrary()—— 二者用途不同,不要在同一个应用中随意切换。


















