4

作为非 Android 人员的序言(一些 Linux 人员可能知道此信息的答案):

Android 中的每个应用程序都在 Dalvik 虚拟机的一个实例中运行。启动应用程序时,一个名为 ActivityManager 的实体会写入管道以通知另一个实体 Zygote 需要启动应用程序。Zygote 是一个空白的 Dalvik VM 实例,预加载了库,当通过管道被召唤时,它会克隆自己,并且克隆会降低与要启动的应用程序关联的 Linux 用户的权限级别。这可以在启动应用程序时节省时间和内存 - 考虑重新加载所有库并每次都进行所有设置的替代方案。

我的问题是在 Zygote 中加载了一个特定的库,我想在这个特定的过程中关闭它,因为我想使用我自己的库版本。我已经将我的本机代码与我的 .so 文件链接起来,该文件被复制到适当的文件夹中,并在应用程序启动时通过 Java 层“System.load('xyz')”加载,但是当我的代码运行时,它正在调用原始系统库的功能,而不是我的。当我运行“cat /proc/NNNN/maps”时,我可以看到旧库和我的一样在内存中。

有没有办法在我的应用程序中关闭该特定库?如果没有,有没有办法确保对该库中函数的任何/每个调用都传递给我的版本而不是旧版本?

谢谢!

4

1 回答 1

3

在最好的情况下关闭共享库(使用dlclose())很棘手,因为它会取消映射库的代码。如果稍后调用该代码——可能是 C++ 析构函数——程序将立即崩溃。由于该库是由您的代码以外的代码加载的,因此在您取消映射时,另一个线程完全有可能正在执行该库中的代码,再次导致崩溃。

所以,不要那样做。:-)

如果您可以将您的库版本构建为静态库并将其直接链接到您的代码中,您应该能够完全避免该问题。

FWIW,各种库(特别是 SSL 和 ICU)都链接到 Dalvik,而不是由 zygote 显式加载,因此如果您尝试替换其中一个,/system/lib无论您是否从 zygote 分叉,您都将获得该版本。

于 2013-04-22T18:03:56.087 回答