
本文详解 Android 7.0 及以上版本(尤其 AOSP 系统级服务)中 UnsatisfiedLinkError: dlopen failed: library not found 的根本成因,重点揭示 vendor: true 在 Android.bp 中对库可见性的影响,并提供符合官方构建规范的安全修复方式。
本文详解 android 7.0 及以上版本(尤其 aosp 系统级服务)中 `unsatisfiedlinkerror: dlopen failed: library not found` 的根本成因,重点揭示 `vendor: true` 在 android.bp 中对库可见性的影响,并提供符合官方构建规范的安全修复方式。
在 Android 7.0+(尤其是基于 AOSP 的定制系统如 ARPI13)中,JNI 库加载失败并非仅由路径或 ABI 错误导致,而常源于系统级库可见性策略的变更。您遇到的错误:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libjavanativetestservice_jni.so" not found
虽显示库文件已存在于 vendor/lib64/ 且已列入 vendor/etc/public.libraries.txt,但关键问题在于:该库在 Soong 构建系统中被错误标记为 vendor: true。
? 为什么 vendor: true 会导致加载失败?
在 Android.bp 中,vendor: true 表示该模块仅对 vendor 分区内的进程可见(即仅限 vendor HAL、vendor service 等运行于 vendor 域的组件使用)。而您的 JavaNativeTestService 是一个 system 分区应用(APK 或 system_server 扩展服务),其 ClassLoader 运行在 system 域上下文中。即使 .so 文件物理存在于 vendor/lib64/,若构建时声明 vendor: true,Soong 会:
- 阻止该库被链接到 system 分区可执行文件或 APK;
- 在 ld.config.txt 或 public.libraries.txt 的生效逻辑中忽略该条目(尤其当 public.libraries.txt 本身未被 vendor 域动态加载器识别时);
- 导致 dlopen() 在 system 域调用链中完全无法解析该库路径。
✅ 正确做法:对需被 system 应用或服务加载的 JNI 库,应使用 vendor_available: true(而非 vendor: true),并确保其 specific: false 或显式声明 system: true。
✅ 正确修复步骤(以 Android.bp 为例)
将原错误配置:
cc_library_shared {
name: "libjavanativetestservice_jni",
vendor: true, // ❌ 错误:锁死为 vendor-only
srcs: ["jni/native-lib.cpp"],
shared_libs: ["liblog", "libc++"],
}修正为:
cc_library_shared {
name: "libjavanativetestservice_jni",
vendor_available: true, // ✅ 允许 vendor 和 system 均可使用
system: true, // ✅ 显式声明 system 分区可用(推荐)
srcs: ["jni/native-lib.cpp"],
shared_libs: ["liblog", "libc++"],
// 可选:指定导出头文件供 Java 层引用
export_include_dirs: ["jni/"],
}同时确认 public.libraries.txt 已正确安装(您已做到):
PRODUCT_COPY_FILES += \
vendor/alvenan/aosp_bench/bench_test_jni/public.libraries.txt:$(TARGET_COPY_OUT_VENDOR)/etc/public.libraries.txt并在 Android.mk 或 BoardConfig.mk 中确保启用公共库机制(AOSP 默认开启):
# 确保以下配置存在(通常默认启用) BOARD_USES_VENDOR_PUBLIC_LIBRARIES := true
? 验证与调试建议
-
检查最终生成的 public.libraries.txt 是否生效
在设备上执行:adb shell cat /vendor/etc/public.libraries.txt | grep javanativetest # 输出应为:libjavanativetestservice_jni.so
确认 APK 中是否包含对应 ABI 的 .so(双重保障)
解压 APK 后检查 lib/arm64-v8a/ 下是否存在 libjavanativetestservice_jni.so —— 即使走 vendor 路径,APK 内置仍是 fallback 最佳实践。-
查看 dlopen 实际搜索路径(需 root)
adb shell su -c 'cat /proc/<pid>/maps | grep javanativetest' # 若无输出,说明未加载;若有,验证基址与 vendor/lib64 匹配
⚠️ 注意事项与最佳实践
- 不要滥用 system/etc/public.libraries.txt:该文件仅对 system 分区进程有效;vendor 分区进程应使用 vendor/etc/public.libraries.txt,且需匹配 BOARD_USES_VENDOR_PUBLIC_LIBRARIES。
- 避免手动修改 system/etc/public.libraries.txt:该文件由 system 分区构建生成,硬编码易被 OTA 覆盖;应通过 PRODUCT_COPY_FILES 从 vendor 源码注入。
- 优先使用 System.loadLibrary() 而非 System.load():前者自动处理 lib 前缀与 .so 后缀,并支持 ABI 自适应;后者需传入绝对路径,易引发权限与 SELinux 问题。
- NDK 版本一致性:确保 APP_PLATFORM(如 android-21)与目标设备 API Level 兼容,避免 dlopen 因符号版本不匹配失败。
✅ 总结
UnsatisfiedLinkError: library not found 在 Android 7.0+ 系统服务场景下,往往不是“文件不存在”,而是构建属性与运行域不匹配所致。vendor: true 是典型的“过度隔离”陷阱——它让库在 vendor 分区“存在”,却在 system 分区“不可见”。修正为 vendor_available: true + system: true,配合标准 public.libraries.txt 注册,即可安全、合规地实现跨分区 JNI 调用,无需 hack LoadedApk.java 或修改系统源码,真正遵循 AOSP 官方架构设计原则。


















