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

时间:2013-11-23 10:38:00

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

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

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

引入后者以支持以下流程(伪代码如下):

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

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