2013-04-22 64 views
3

作为非Android人的序言(某些Linux民众可能知道此信息的答案):有没有办法在Android中关闭动态加载的库?

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

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

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

谢谢!

+0

“关闭”,如卸载以前加载的共享库?似乎没有办法。请参阅:https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/59Xu4kKjgnA和https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/ sf56xVIySfI – MarsAtomic 2013-04-22 16:46:25

+0

@MarsAtomic:这些帖子是关于卸载应用程序本身加载的库,稍有不同。如果你管理自己的'dlopen()'/'dlclose()'调用,而不是依赖'System.load()',你可以实际做到。由于一切都在应用程序的控制之下,因此可以安全地进行操作。这真的是你想更新共享库而不重新启动应用程序(或更可能是服务)的场景,而这里的问题是关于覆盖系统的库副本。 – fadden 2013-04-22 18:10:37

+0

大家好!实际上,我想卸载Zygote中默认加载的库,以便我可以自己加载不同版本的库(在我的DVM实例中),并将通常会转到原始库的调用转到我的库中。 – ZachM 2013-04-24 18:29:24

回答

2

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

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

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

FWIW,各种图书馆(特别是SSL和ICU)都链接到Dalvik中,没有明确地由zygote加载,所以如果你试图替换其中一个,你会得到/system/lib版本,不管你是从哪个分支合子与否。

+0

嗨fadden!谢谢!我同意不这样做。我拉了一些其他整洁的内存技巧直接从内存中取消映射,但我最终选择使用dlopen()来自己打开它,然后只需使用dlsym()就可以取出我需要的函数指针。这更可靠。 – ZachM 2013-04-24 18:32:27

+0

此外,作为关于正确性的说明 - 如果您正在使用小型库和/或仅将其与一个应用程序一起使用,我会建议fadden的答案涉及使用静态库。我为Android的自定义构建构建了一套应用程序,因此将它静态链接到20个不同的东西中会浪费,因此在这种情况下,请使用dlopen()/ dlsym()/ dlclose()的建议! – ZachM 2013-04-24 18:33:56

+0

FWIW,你的方法就是为什么JNI有'UnregisterNatives' - 如果你用'dlsym()'找到的任何符号都是本地方法实现,你可以在调用'dlclose()'之前注销它们。 – fadden 2013-04-24 19:26:31

相关问题