为同一共享库调用System.loadLibrary两次
Calling System.loadLibrary twice for the same shared library
我遇到了两个jar库使用同一个共享库的情况。在每个库中,"主接口"类加载带有System.loadLibrary
的.so文件。我的问题是:如果用户决定在一个项目中使用这两个jar库,那么对同一.so文件的System.loadLibrary
的第二次调用会引起任何异常吗?还是系统"如何处理"以防止共享库被加载两次?或者可能有一种"众所周知的模式"来处理这种情况?
jni包装器的目标是在android上使用。我是这两个包装器库的作者,所以回答问题时您可以完全控制java源代码。
根据apidocs的说法,这应该不是问题:"如果用相同的库名称多次调用此方法,则第二次和随后的调用将被忽略。">
我发现了一个非常狭窄的用例,当这将是一个问题时。
如果您运行的是清单中有android:sharedUserId="android.uid.system"
的Android系统应用程序,或者预装到设备上,或者使用平台证书签名,并且您试图调用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将重新启动。
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 如何在c++中使用system()来运行包含空格的python脚本
- System.InvalidCastException - SQL to C++ - safe_cast<float>
- C++/CLI System.AccessViolation在托管类中调用非托管函数时出现异常
- 来自 Android 应用程序内部的 boost 类型的 boost::wrapexcept<boost::system::system_error> 的未捕获异常
- 程序在使用 system() 启动另一个可执行文件时停止
- 为什么我的 DeviceInformation 对象没有 System.Devices.InterfaceClassGuid 属性?
- 为什么"using System;"不被视为不良做法?
- C++ 合并字符串以'system'函数错误
- Windows 链接器是否使用 LoadLibrary 解析 DLL 中未定义的符号?
- 如何将 std::filesystem::p ath 转换为 LPCSTR,以便在 LoadLibrary() 变体之一
- 为什么 LoadLibrary 失败,而 LoadLibraryA 成功加载 DLL?
- System.AccessViolationException:shared_ptr C# .NET 和 C++ 应用程
- Java System.loadLibrary 不会在 /usr/lib/x86_64-linux-gnu/ 文件夹中查
- 为同一共享库调用System.loadLibrary两次
- 通过JNI调用System.loadLibrary()不会加载本机方法
- JNI-我可以在不为本机插件调用System.loadLibrary的情况下使用RegisterNatives吗
- Play Framework - System.loadLibrary() 每个线程只有一次
- 用java中的System.loadLibrary()加载的.dll的搜索路径
- Android Studio在System.loadLibrary(libName)中崩溃