使用JNI加载另一个JNI库?

5

我需要实现一个本地方法,例如 "public native void someFunc();"。我有两个库,libabc.so和libdef.so。Java使用System.loadLibrary();加载libabc.so(它没有实现该方法),但JNI的实现在libdef.so中。目前,在libabc.so中我正在执行以下操作。

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved){
JNIEnv *env;
jclass cls;
jmethodID get_load_id;
jstring name;

jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
cls = env->FindClass("java/lang/System");
get_load_id = env->GetStaticMethodID(cls, "load", "(Ljava/lang/String;)V");
name = env->NewStringUTF("/lib/libdef.so");
env->CallStaticVoidMethod(cls, get_load_id, name);

return JNI_VERSION_1_4;
}

然而,我遇到了一个错误(来自Android Logcat):“/lib/libdef.so中的JNI_OnLoad返回了错误版本(-1)”。如果我直接从Java加载libdef.so,则不会出现此错误。此外,如果我创建另一个本地方法“loadDef()”并使用相同的代码实现它,它也可以工作。我认为问题在于使用jvm->GetEnv(),但我不确定。此外,我甚至不知道这是否能让我实现我想要的功能(使用一个JNI库来加载另一个来实现)。我之所以这样做是因为原因比较复杂,但没有其他选择。

哦,还有一些信息。在logcat上,在出现错误之前,我看到“尝试加载lib / libdef.so 0x0”我认为这意味着它正在尝试将库加载到0x0。为什么会这样? - Yifan
我不确定期望 loadLibrary() 可重入是否合理。这个函数可以在正常的本地方法中工作似乎支持了这种怀疑。为什么不跟我们分享那个复杂的原因 —— 或许我们可以帮你想到一个替代方案。 - Ernest Friedman-Hill
我可以尝试使用RegisterNatives,但这意味着我必须手动加载库并找到函数所在的位置。如果loadLibrary()不可重入并且这是问题所在,那么我可能不得不这样做。 - Yifan
你可以使用操作系统内置的本地库加载功能。如果需要访问另一个DLL,只需在C++代码中按照通常的方式执行即可。 - Chris Dennett
1个回答

0

虽然我仍然没有解决在JNI_OnLoad中加载另一个JNI库的问题,但我找到了第一个被调用的本地函数,将其替换,并在该函数中运行loadLibrary代码。然后我再次从JNI调用本地方法,它会运行方法的新版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接