【问题标题】:Calling System.loadLibrary twice for the same shared library为同一个共享库调用 System.loadLibrary 两次
【发布时间】:2014-02-19 10:05:24
【问题描述】:

我有两个jar库使用同一个共享库的情况。 在每个库中,“主界面”类加载带有System.loadLibrary 的.so 文件。 我的问题是:如果用户决定在一个项目中使用这两个 jar 库,那么对同一 .so 文件的第二次调用 System.loadLibrary 会导致任何异常吗?还是系统“以某种方式处理”以防止共享库被加载两次?或者也许有一种“众所周知的模式”来处理这种情况?

jni 包装器的目标是在 android 上使用。我是这两个包装器库的作者,因此回答您可以完全控制 Java 源代码。

【问题讨论】:

  • 我没有测试过,但是根据apidocs应该没有问题:“如果这个方法被多次调用,同一个库名,第二次和后续的调用都会被忽略。”
  • 谢谢,它似乎完全回答了我的问题。把它作为答案而不是评论,以便我可以接受它。

标签: java android c++ java-native-interface


【解决方案1】:

根据apidocs,这应该不是问题:“如果使用相同的库名多次调用此方法,则忽略第二次和后续调用。”

【讨论】:

  • 帮助未来可能正在搜索“幂等”这个词的人,就是这样。
【解决方案2】:

我发现了一个非常狭窄的用例,这将成为一个问题。

如果您正在运行 Android 系统应用程序,android:sharedUserId="android.uid.system" 在清单中,预安装到设备或 signed with the platform certificate,并且您尝试调用 System.loadLibrary 两次以加载相同的库(通过运行相同的应用程序两次,或创建两个单独的系统应用程序加载相同的库),Android 将重新启动。

从该库调用 JNI 方法,如果尚未加载,则在 android.uid.system 进程中运行时不会产生异常,与普通 Android 应用程序一样 - 它将重新启动 Android。

为防止这种情况发生,并确定库是否已加载,您可以读取文件 /proc/self/maps 并在那里搜索您的库名称。 ClassLoader 和反射在这里无济于事 - 即使尚未加载库,它们也会将 JNI 方法显示为可访问的。

请注意,您不能这样做if (Runtime.getRuntime().exec("/system/bin/grep <library-name> /proc/self/maps").waitFor() == 0) - SELinux 禁止系统进程启动任何外部命令,您必须从 Java 代码中读取文件。

另一个怪癖是库必须预先安装到设备上的/system/lib 目录 - 如果您将库与您的应用程序捆绑在一起,并将应用程序安装到设备上,库将在/data/app/..../lib 中结束,当您将尝试从/data 分区加载它,你已经猜到了——Android 将重新启动。

【讨论】:

  • 实际上是一个狭窄的场景;)。但是感谢您的贡献。
猜你喜欢
  • 2019-04-02
  • 1970-01-01
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 2019-04-17
  • 1970-01-01
  • 2011-08-07
  • 2011-09-26
相关资源
最近更新 更多