【问题标题】:Android app linking with updated aosp libraries与更新的 aosp 库链接的 Android 应用程序
【发布时间】:2015-01-11 18:47:46
【问题描述】:

这是我上一个问题的改写。

我有一个测试应用程序,我正在尝试与 ibicuuc 和 libicui18n 链接。 (这是大型项目的第一步)。

我将这些作为预建库包含在我的项目中

LOCAL_SHARED_LIBRARIES := libicuuc libicui18n

从 git 存储库按原样编译:

https://android.googlesource.com/platform/external/icu4c/

这是来自 clean 的构建日志:

$ ndk-build
[armeabi-v7a] Prebuilt       : libicui18n.so <= /usr/local/opt/android/libs/libs/armeabi-v7a/
[armeabi-v7a] Install        : libicui18n.so => libs/armeabi-v7a/libicui18n.so
[armeabi-v7a] Prebuilt       : libicuuc.so <= /usr/local/opt/android/libs/libs/armeabi-v7a/
[armeabi-v7a] Install        : libicuuc.so => libs/armeabi-v7a/libicuuc.so
[armeabi-v7a] Compile++ thumb: main <= main.cc
[armeabi-v7a] SharedLibrary  : libmain.so
[armeabi-v7a] Install        : libmain.so => libs/armeabi-v7a/libmain.so

但当应用程序运行时,它与 /system 中的库链接,而不是我的库

root@flo:/proc/27311 # grep icu maps                                           
40665000-40756000 r-xp 00000000 b3:16 722        /system/lib/libicuuc.so
40756000-4075f000 r--p 000f0000 b3:16 722        /system/lib/libicuuc.so
4075f000-40760000 rw-p 000f9000 b3:16 722        /system/lib/libicuuc.so
4076a000-4089a000 r-xp 00000000 b3:16 721        /system/lib/libicui18n.so
4089b000-408a2000 r--p 00130000 b3:16 721        /system/lib/libicui18n.so
408a2000-408a3000 rw-p 00137000 b3:16 721        /system/lib/libicui18n.so
6fe85000-710ac000 r--s 00000000 b3:16 897        /system/usr/icu/icudt51l.dat
73454000-7467b000 r--s 00000000 b3:16 897        /system/usr/icu/icudt51l.dat

由于“我的”库是 HEAD,它们与库的 53 版本链接,而不是系统 51,并且应用程序无法找到符号。

如何让运行时链接器从 /data/data/.../lib 加载我的库?

(这个项目的下一阶段是构建一些不属于aosp的库,需要libicu)

如果我在 java 静态中使用 System.loadLibrary(),似乎添加了正确的库,但似乎仍然没有“替换”/system 版本

D/dalvikvm(28077): Trying to load lib /data/app-lib/com.example.test.nativelibs-2/libicuuc.so 0x41e65670
D/dalvikvm(28077): Added shared lib /data/app-lib/com.example.test.nativelibs-2/libicuuc.so 0x41e65670
D/dalvikvm(28077): No JNI_OnLoad found in /data/app-lib/com.example.test.nativelibs-2/libicuuc.so 0x41e65670, skipping init
D/dalvikvm(28077): Trying to load lib /data/app-lib/com.example.test.nativelibs-2/libicui18n.so 0x41e65670
D/dalvikvm(28077): Added shared lib /data/app-lib/com.example.test.nativelibs-2/libicui18n.so 0x41e65670
D/dalvikvm(28077): No JNI_OnLoad found in /data/app-lib/com.example.test.nativelibs-2/libicui18n.so 0x41e65670, skipping init
D/dalvikvm(28077): Trying to load lib /data/app-lib/com.example.test.nativelibs-2/libmain.so 0x41e65670

谢谢

【问题讨论】:

    标签: android android-ndk android-source


    【解决方案1】:

    我认为最安全/最简单的方法是重命名您自己提供的库,这只需要对上游源项目进行细微调整。 (如果您只有一个库,则只需重命名已构建的 .so 即可,但是当您有两个时,您需要从头开始重命名第一个库,以使另一个库使用正确的 soname 引用它。 )

    人们可能认为System.loadLibrary 会在查看/system/lib 之前先查看您应用的私有目录,但问题可能是您的进程之前已经加载了这些库,并且仿生链接器不会加载如果进程已经加载了同名的库,则再次库。

    如果旧库已经加载,这也可能导致另一个问题,您的代码仍然调用旧版本的库,或者相反,系统框架调用新的(可能不兼容的)库。这是因为这些库被加载到全局命名空间中,并且在全局命名空间中只能有一个符号定义。 (对此的一种解决方案是使用符号版本控制,但仿生不支持。)如果遇到这种情况,您可以希望它支持新版本的库,并且它与系统库兼容期待旧的。或者为库中的所有非静态符号添加前缀以使其唯一。

    【讨论】:

    • 嗨,谢谢,这听起来很合理,替代策略似乎是从设备中“拉”系统/lib .so 并针对这些进行编译时链接,然后运行时将正确链接,但是这种方法似乎也存在问题,因为应用程序不一定是跨设备兼容的,因为不同的硬件可能已经进行了代码调整。对此选项有何想法?
    • 我已经用 system.loadLibrary() 的调试输出更新了这个问题,它显示了正在加载的(新)库,但显然不是“替换”从 /system/lib 加载的那些
    • 是的,这正是风险 - 因为这些库无法保证,它们可能会在设备之间发生变化(甚至根本不存在),或者在版本之间发生变化。如果你这样做,你需要评估风险(例如检查历史,这些库在不同版本之间有多少变化,它在实践中是否运作良好)并查看与制作库相比的权衡独特。实际上,我认为硬件供应商没有太多理由接触这些库,但最好不要依赖不受支持的细节。
    • libmyicuuc 和 libmyicui18n 经过测试并且可以正常工作 - 谢谢!小工作区需要定位 icudt53l.dat 存根数据,当前存储在 /sdcard 上进行测试;正在开发 mod 以在 apk 中正确部署它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多