2015-02-24 204 views
0

我們有一個本地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以同樣的方式,一切正常。這非常令人沮喪,因爲我在網上可以閱讀的所有內容都表明這應該可以正常工作。

回答

1

最後,我看着源的System.loadLibrary:

@CallerSensitive 
public static void loadLibrary(String libname) { 
    Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname); 
} 

啊哈! Reflection.getCallerClass()是關鍵。沒有來電者的課程!它來自直接的C++。該解決方案是相當簡單,寫身邊System.load *()的一個門面,我們可以從調用C++和將扭虧爲盈,並調用系統方法:

public class SystemFacade { 
    public static void load(String path) { 
     java.lang.System.load(path); 
    } 
    public static void loadLibrary(String name) { 
     java.lang.System.loadLibrary(name); 
    } 
} 

瞧,它的工作原理。據推測,Java通過JNI調用而不是C++的任何變體都可以避免這個問題。 @CallerSensitive標籤似乎是一個線索;不要通過JNI調用它們!我希望這篇文章能夠拯救別人我經歷的挫折感。我仍然困惑爲什麼負荷似乎成功,但沒有找到符號。

+0

你爲什麼要去調用'dyload'或'LoadLibraryEx'? – 2015-02-24 23:47:50

+0

因爲LoadLibraryEx並沒有使Java可以調用C++代碼。我們的應用程序是一個重要的c + +/java混合,兩種語言互相呼叫。我實際上不寫那個JNI代碼。我們有一個複雜的包裝生成器,可以將這些調用從C++中分離出來。加載本地庫只是集成工作的一小部分。在我們嵌入jvm的時候很容易從C++調用。除了它沒有像預期的那樣工作之外,花費了大量精力去找出原因。我將寫一篇關於jni陷阱的博客。 – Wheezil 2015-02-26 01:10:00

+1

陷阱。這就說得通了。有興趣看到博客文章,我希望你在這裏鏈接。 – 2015-02-26 01:12:27