JNI-我可以在不为本机插件调用System.loadLibrary的情况下使用RegisterNatives吗

JNI - Can I use RegisterNatives without calling System.loadLibrary for native plugins?

本文关键字:情况下 loadLibrary RegisterNatives System 调用 我可以 插件 本机 JNI-      更新时间:2023-10-16

我有一个使用插件的C++应用程序(它动态加载某些共享的lib文件)。我很难理解从Java调用动态加载的本机代码需要做什么。

我是否有使用System.loadLibrary/System.load来"预加载"本机共享对象("插件"),以便能够调用该本机代码?或者,在将插件加载到我的本机代码中后,我只可以从插件中调用RegisterNatives吗?我已经为我的主要本机应用程序库调用了System.loadLibrary——它是本机库加载的后续插件,这个问题就是为了这个插件。

如果我可以只调用RegisterNatives,如果我突然决定卸载一个插件,JVM尝试调用其中的本机方法,会发生什么?

至少Android VM要求在实例化类时必须"注册"所有本机方法。这就是为什么System.load()通常在静态构造函数中调用,而不是稍后调用。

解析本机方法的两种方法是通过JNI_OnLoad()中的RegisterNatives()或通过名称匹配(javah报告的C导出函数名称)。

您可以在所有加载的模块中查找RegisterNatives()的函数指针,也可以加载更多模块并从中获取指针。RegisterNatives()可以在任何时候被调用,如果你真的想卸载一些插件,你可以使用UnregisterNatives()

后者是为了支持以下流程而引入的(伪代码如下):

SwitchPlugin() {
    UnregisterNatives();
    unloadPlugin(oldHandle);
    newHandle = loadPlugin(newPluginName);
    RegisterNatives();
}

如果您的应用程序试图使用在卸载的插件中实现的本机方法,或者在使用UnregisterNatives()注销后,它可能会崩溃。