在 Android 中,如何强制本机代码使用我的共享库版本,而不是系统的?

In Android, how to force the native code to use my version of a shared library, instead of the system's?

Android 已经有了 PCRE 共享库(“/system/lib/libpcre.so”),但它是在没有 Unicode 支持的情况下编译的,所以我为 [=16= 构建了自己的 PCRE 版本].我的本机代码链接到 PCRE 共享库。但是,当我 运行 我的应用程序时,它使用系统版本的 PCRE,而不是我构建的版本,即使我的 APK 确实包含我的 PCRE 版本。我如何让它使用我的 PCRE 版本而不是系统的?通常在 Linux 我使用 "LD_LIBRARY_PATH" 或 "RPATH",但在 Android 我不知道如何使用它们,如果可能的话。

我认为唯一的方法是重命名库(例如 libpcre_myapp)。

请注意,仅重命名文件可能还不够,但要更改 SO_NAME ELF 属性。

您可以在加载主库​​之前load("your-path-to-lib")。使用 this API 您可以在任意位置加载本机库。但最简单的方法是依赖构建和安装程序的默认行为,这将打包本机库(名为 libsomething.so ) 它在 libs/<ABI> 文件夹中找到的,放入 APK 文件中,并将与目标匹配的 ABI 变体解压到

getContext().getApplicationInfo().nativeLibraryDir

(这是在 API 级别 9 中添加的)

如果库是预加载的,则您无法将库与系统库并排放置,因为 bug 包含旧版本的 Android。不过,您可能会成功手动卸载它,使用 dlclose():

handle = dlopen("<libname>", RTLD_NOLOAD);
dlclose(handle);
dlclose(handle); // twice, because dlopen() increments ref count

您可能会在一个单独的小 dlclose_helper.so 中进行这些操作。在加载主库​​之前加载这个辅助加载,它需要 <libname>.

的私有版本

为 API 级别 23 引入了一个修复程序,使我们最终可以同时加载 dir1/libx.sodir2/libx.so(参见 official doc)。

请注意,对于 API 级别 24,还引入了 new restrictions 以限制对系统库的访问(您只能加载列入白名单的库)。