JNI - 我可以在不调用 System.loadLibrary 的本地插件的情况下使用 RegisterNatives 吗?
Posted
技术标签:
【中文标题】JNI - 我可以在不调用 System.loadLibrary 的本地插件的情况下使用 RegisterNatives 吗?【英文标题】:JNI - Can I use RegisterNatives without calling System.loadLibrary for native plugins? 【发布时间】:2013-11-23 10:37:59 【问题描述】:我有一个使用插件的 C++ 应用程序(它动态加载某些共享库文件)。我无法理解从 Java 调用动态加载的本机代码需要做什么。
我是否必须使用 System.loadLibrary/System.load 来“预加载”本机共享对象(“插件”)以便能够调用该本机代码?或者我可以只在插件中调用 RegisterNatives 在我的本机代码中加载它之后?我已经为我的主要本机应用程序库调用了 System.loadLibrary - 它是本机库加载的后续插件。
如果我只调用 RegisterNatives 就可以逃脱,如果我突然决定卸载插件并且 JVM 尝试调用其中的本机方法会发生什么?
【问题讨论】:
【参考方案1】:至少 android VM 要求在实例化类时必须“注册”所有本机方法。这就是为什么System.load()
通常在静态构造函数中调用,而不是稍后调用。
解析本机方法的两种方法是通过JNI_OnLoad()
中的RegisterNatives()
或通过名称匹配(javah
报告的 C 导出函数名称)。
您可以在所有加载的模块中查找RegisterNatives()
的函数指针,或者加载更多模块并从中获取指针。 RegisterNatives()
可以随时调用,如果你真的想卸载一些插件可以使用UnregisterNatives()
。
引入后者是为了支持以下流程(伪代码如下):
SwitchPlugin()
UnregisterNatives();
unloadPlugin(oldHandle);
newHandle = loadPlugin(newPluginName);
RegisterNatives();
如果您的应用尝试使用在未加载的插件中实现的本机方法,或者在使用 UnregisterNatives()
注销后,您的应用可能会严重崩溃。
【讨论】:
我不相信最初的句子是真的,好像它是,声明一个本地方法并在以后(但在使用之前)加载实现是行不通的。事实上确实如此,如果跳过加载,运行时异常只会在尝试使用缺失的方法时发生,不会在实例化它所属的类时发生。跨度> @chris-stratton:你说的是 Android 实现吗? 只要我事先加载了所有的类 id,在加载原生插件后调用 RegisterNatives 似乎工作正常以上是关于JNI - 我可以在不调用 System.loadLibrary 的本地插件的情况下使用 RegisterNatives 吗?的主要内容,如果未能解决你的问题,请参考以下文章
System.load()与System.loadLibrary()
System.load(String filename)和System.loadLibrary(String libname)的区别
JNI - 我可以在不调用 System.loadLibrary 的本地插件的情况下使用 RegisterNatives 吗?