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