System.load要求传入动态库的完整绝对路径(含文件名与扩展名),不支持相对路径或自动补全;System.loadLibrary仅接受库名,由JVM根据java.library.path自动拼接前缀/后缀并在预设目录中查找。

System.load 和 System.loadLibrary 在加载路径上的核心区别,不是“绝对 vs 相对”路径之争,而是显式路径定位 vs 隐式路径查找机制的区别。关键在于:System.load 强制要求绝对路径(不支持纯相对路径),而 System.loadLibrary 根本不接受路径,只认库名,并依赖 java.library.path 的预设目录列表去自动匹配。
System.load:必须传入完整、可访问的绝对路径
- 参数是动态库文件的全路径字符串,包括文件名和扩展名(如
.so、.dll) - 路径必须能被 JVM 当前进程直接读取(权限、存在性、挂载状态都需满足)
- 不会做任何路径拼接或前缀/后缀补全:传什么路径,就尝试打开什么文件
例如:
System.load("/data/app/com.example.myapp-1/lib/arm64/libnative.so"); // ✅ 正确(Android)
System.load("/sdcard/mylib.so"); // ❌ 大概率失败:/sdcard 通常无执行权限,且 Android 10+ 默认禁止从外部存储加载 so
System.load("libnative.so"); // ❌ 错误:不是绝对路径,JVM 不会自动补前缀或查路径
System.load("./libnative.so"); // ❌ 错误:相对路径不被支持,会抛 UnsatisfiedLinkError ⚠️ 注意:即使你用
new File("libnative.so").getAbsolutePath()拼出路径,若该路径不在可执行上下文中(如未在应用私有目录或/data/data/包名/lib/下),依然会失败。
System.loadLibrary:只传库名,由系统自动拼接并搜索
- 参数只是库名(不含
lib前缀、不含.so/.dll后缀) - JVM 会按规则拼成实际文件名(如
"native"→libnative.soon Android/Linux) - 然后依次在
java.library.path所列的每个目录中查找该文件 - 你无法控制“搜哪个目录先”,但可以影响
java.library.path的内容(如启动时加-Djava.library.path=...,或 Android 中通过Application.nativeLibraryDir获取正确路径)
例如:
System.loadLibrary("native"); // ✅ 自动查找 libnative.so
// 它会在以下典型位置依次尝试(Android 示例):
// - /data/app/包名-1/lib/arm64/
// - /system/lib64/
// - /vendor/lib64/
// (具体顺序由 Runtime 决定,不可硬编码) 验证当前有效路径:
System.out.println(System.getProperty("java.library.path")); 实际开发中怎么选?看这三点
-
调试阶段快速加载自定义 so → 用
System.load(绝对路径),比如从getFilesDir()或getApplicationInfo().nativeLibraryDir拿到路径再拼接 -
发布 APK,so 已打包进
src/main/jniLibs/→ 必须用System.loadLibrary("xxx"),这是唯一可靠方式 -
so 有依赖关系(如
liba.so依赖libb.so) →-
System.load:必须手动按依赖顺序load每个 so(先libb.so,再liba.so),且所有 so 都得用绝对路径 -
System.loadLibrary:只要libb.so和liba.so都放在java.library.path的同一目录下,加载liba.so时系统会自动找到并加载libb.so
-
不复杂但容易忽略

















