我們有一個本地C++應用程序,用於創建嵌入式JVM。這個JVM中的類使用SWIG包裝器回調到C++對象方法中(儘管SWIG的使用並不重要,它可能也很容易成爲由javah生成的本地函數存根)。例如,我們有一個Java類與一個本地方法,如:通過JNI調用System.loadLibrary()不會加載本地方法
package net.foo;
public class CppWrapJNI {
public final static native long foo(
long l, Stuff jarg1_, String s
);
}
有一個C++ DLL一個對應的實現:
extern "C" {
__declspec(dllexport) jlong JNICALL
Java_net_foo_CppWrapJNI_1foo(
JNIEnv *jenv, jclass jcls,
jlong jarg1, jobject jarg1_, jstring jarg2
) {
return 1;
}
}
比方說,這個DLL被命名爲「foo.dll」。
然後,我們試圖使JVM加載通過JNI的DLL,使用如下代碼:
jclass cls = env->FindClass("java/lang/System");
jmethodID mid = env->GetStaticMethodID(
cls, "loadLibrary", "(Ljava/lang/String;)V"
);
jstring jstr = env->NewStringUTF("foo.dll");
env->CallStaticVoidMethodV(cls, mid, jstr);
這一切工作,並調用調用LoadLibrary()報告未顯示任何錯誤(JNI異常處理在這裏,但我們這樣做)。然而,CppWrapJNI.foo以後的()調用失敗,就像一個錯誤:
java.lang.UnsatisfiedLinkError:
net.foo.CppWrapJNI.foo(JLnet/foo/Stuff;Ljava/lang/String;)J
奇怪的是,如果我用Java寫純粹是一個測試工具,調用LoadLibrary以同樣的方式,一切正常。這非常令人沮喪,因爲我在網上可以閱讀的所有內容都表明這應該可以正常工作。
你爲什麼要去調用'dyload'或'LoadLibraryEx'? – 2015-02-24 23:47:50
因爲LoadLibraryEx並沒有使Java可以調用C++代碼。我們的應用程序是一個重要的c + +/java混合,兩種語言互相呼叫。我實際上不寫那個JNI代碼。我們有一個複雜的包裝生成器,可以將這些調用從C++中分離出來。加載本地庫只是集成工作的一小部分。在我們嵌入jvm的時候很容易從C++調用。除了它沒有像預期的那樣工作之外,花費了大量精力去找出原因。我將寫一篇關於jni陷阱的博客。 – Wheezil 2015-02-26 01:10:00
陷阱。這就說得通了。有興趣看到博客文章,我希望你在這裏鏈接。 – 2015-02-26 01:12:27