
本文详解 Android 7.0 及以上版本中,系统级 Service 加载 JNI 共享库(.so)时出现 UnsatisfiedLinkError: dlopen failed: library "xxx.so" not found 的根本原因,重点剖析 vendor: true 构建属性对库可见性的影响,并提供可落地的构建配置修复方案。
本文详解 android 7.0 及以上版本中,系统级 service 加载 jni 共享库(.so)时出现 `unsatisfiedlinkerror: dlopen failed: library "xxx.so" not found` 的根本原因,重点剖析 `vendor: true` 构建属性对库可见性的影响,并提供可落地的构建配置修复方案。
在 Android 系统开发(尤其是 AOSP 定制项目如 ARPI13)中,为系统服务(如 JavaNativeTestService)集成 JNI 功能时,即使 .so 文件已正确部署至 vendor/lib64/、且已声明于 vendor/etc/public.libraries.txt,仍可能遭遇 java.lang.UnsatisfiedLinkError: dlopen failed: library "libjavanativetestservice_jni.so" not found。该错误表面是“库未找到”,实则源于 Android 构建系统对 native 库的可见性管控机制——而关键症结往往隐藏在 Android.bp 的构建属性配置中。
根本原因:vendor: true 阻断了运行时符号可见性
在 AOSP 中,Android.bp 文件用于定义模块构建规则。当为 JNI 库(如 libjavanativetestservice_jni.so)设置 vendor: true 时,构建系统会将其标记为 纯 vendor 专属模块,并施加严格隔离:
- ✅ 编译期:成功生成 .so 并拷贝至 vendor/lib64/;
- ❌ 运行时:Android Runtime(ART)在加载阶段拒绝将该库暴露给非 vendor 进程(包括 system_server 或自定义系统服务),即使其路径合法、名称匹配、且已列入 public.libraries.txt。
这是因为 vendor: true 不仅控制安装路径,更触发了 SELinux 域策略与 linker 的符号可见性过滤。public.libraries.txt 仅对 vendor 分区中被标记为 可公开访问(non-vendor-restricted) 的库生效;而 vendor: true 恰恰使其变为“私有 vendor 库”,导致 System.loadLibrary() 在调用 android_dlopen_ext 时被 linker 主动拒绝。
? 验证线索:日志中 dlopen failed: library "xxx.so" not found 是 linker 的“伪装提示”——实际并非路径缺失,而是权限/可见性拒绝。对比 dlopen failed: ... has invalid shdr offset 等真实文件解析错误,可确认此为策略拦截。
正确修复方案:移除 vendor: true,改用 specific_vendor_library: true
✅ 推荐做法(兼容性 & 安全性兼顾):
在 Android.bp 中,将 JNI 库模块的 vendor: true 完全移除,并显式声明:
cc_library_shared {
name: "libjavanativetestservice_jni",
// ... 其他配置(srcs, include_dirs等)
specific_vendor_library: true,
// ⚠️ 关键:不再设 vendor: true
}specific_vendor_library: true 的语义是:
- ✅ 仍安装到 vendor/lib64/(满足分区隔离要求);
- ✅ 允许 system 分区中的进程(如你的 Service)通过 public.libraries.txt 加载;
- ✅ 符合 Android 9+ 的 vendor interface 要求,避免 vendor: true 带来的过度隔离。
补充验证与最佳实践
-
双重确认 public.libraries.txt 生效
确保 PRODUCT_COPY_FILES 正确覆盖:PRODUCT_COPY_FILES += \ vendor/alvenan/aosp_bench/bench_test_jni/public.libraries.txt:$(TARGET_COPY_OUT_VENDOR)/etc/public.libraries.txt并检查生成镜像中 /vendor/etc/public.libraries.txt 内容是否包含 libjavanativetestservice_jni.so(无空格、无换行错误)。
-
ABI 与路径严格匹配
- 确认 .so 文件位于 vendor/lib64/(64 位设备)或 vendor/lib/(32 位);
- 使用 file libjavanativetestservice_jni.so 验证 ABI 类型(如 aarch64);
- System.loadLibrary("javanativetestservice_jni") → 自动映射为 libjavanativetestservice_jni.so,命名必须完全一致。
避免 System.load() 替代方案
虽然 System.load("/vendor/lib64/libxxx.so") 可绕过 public.libraries.txt,但违反 Android 安全模型,且在 Android 10+ 受 scoped storage 和 SELinux 策略限制,不推荐用于系统服务。
总结
UnsatisfiedLinkError: dlopen failed: library not found 在系统级 JNI 场景中,90% 以上并非路径或打包问题,而是构建属性引发的运行时可见性阻断。vendor: true 是“银弹陷阱”——它看似强化 vendor 隔离,实则切断了 system 进程与 vendor 库的合法链接通道。移除 vendor: true,改用 specific_vendor_library: true,配合 public.libraries.txt 声明,才是符合 Android 架构演进的安全解法。 开发者应始终以 adb shell cat /proc/<pid>/maps | grep xxx 实时验证库是否真正映射成功,而非仅依赖日志表象。


















