Android 应用与更新的 aosp 库链接

Android app linking with updated aosp libraries

这是对我之前的一个问题的改写。

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

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

LOCAL_SHARED_LIBRARIES := libicuuc libicui18n

从 git 存储库按原样编译:

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

这是干净的构建日志:

$ 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

但是当应用程序是 运行 时,它 link 使用 /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

因为 "my" 库是 HEAD,它们是 link 针对库的版本 53 而不是系统 51 并且应用程序无法找到符号。

如何让 运行 时间 linker 从 /data/data/.../lib 加载我的库?

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

如果我在 java 静态中使用 System.loadLibrary(),似乎添加了正确的库,但似乎仍然没有 'replace' /系统版本

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

谢谢

我认为 safest/simplest 方法是重命名您自己提供的库,这应该只需要对上游源项目进行微小的调整。 (如果你只有一个库,你可以只重命名构建的 .so,但是当你有两个时,你需要从一开始就重命名第一个库,以使另一个库使用正确的 soname 引用它。 )

人们可能希望 System.loadLibrary 在查看 /system/lib 之前先查看您应用程序的私有目录,但问题可能是您的进程之前已经加载了这些库,而 bionic如果进程已经加载了同名库,链接器将不会再次加载库。

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