2016-12-07 99 views
-1

我看到了很多UnsatisfiedLinkError的問題,我知道我的問題是什麼。我得到JNI java.lang.UnsatisfiedLinkError,無法鏈接方法

異常在線程 「主要」 java.lang.UnsatisfiedLinkError中:Test.initCamera(Ljava /郎/字符串; Ljava /郎/字符串; Ljava /郎/字符串; Ljava /郎/字符串;).J

這意味着該DLL已被加載,但它無法找到該方法。但是,我檢查了我的源代碼和Java代碼。方法名稱和參數都可以。我不知道我的代碼有什麼問題。

這是我的代碼。

的Java:

public class Test { 
public native long initCamera(String ip,String port,String username,String pwd); 
public native int snapPic(long id,String savePath,int no); 
static{ 
    System.loadLibrary("dhconfigsdk"); 
    System.loadLibrary("dhnetsdk"); 
    System.loadLibrary("dhplay"); 
    System.loadLibrary("CameraCatcher"); 
} 
public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    Test tNative = new Test(); 
    String ip="192.108.1.108"; 
    String port="37777"; 
    String username="admin"; 
    String pwd="123456"; 
    long cameraId=tNative.initCamera(ip,port,username,pwd); 
    System.out.println(cameraId); 
    String savePath="D:/"; 
    int number=tNative.snapPic(cameraId,savePath,0); 
} 
} 

C++:

JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera 
(JNIEnv * env, jclass c, jstring arg_ip, jstring arg_port, jstring arg_username, jstring arg_pwd) 
{ 
    ...... 
    return lLogin; 
} 


JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic 
(JNIEnv * env, jclass c, jlong arg_id, jstring arg_path, jint arg_no) 
{ 
    ..... 
    return 12; 
} 

這真的讓我發瘋。

更新1: 感謝大家的答覆。我已經像@Mr Tarik所展示的那樣改變了我的代碼。

的Java:

public class CameraCatcher { 
    static{ 
     System.loadLibrary("CameraCatcher"); 
    } 
    public native long initCamera(String ip,String port,String username,String pwd); 
    public native int snapPic(long id,String savePath,int no); 
    public static void main(String[] args) 
    { 
     CameraCatcher tNative = new CameraCatcher(); 
     String ip="192.108.1.108"; 
     String port="37777"; 
     String username="admin"; 
     String pwd="123456"; 
     long cameraId=tNative.initCamera(ip,port,username,pwd); 
     System.out.println(cameraId); 
     String savePath="D:/project/j2ee/Example/result"; 
     int number=tNative.snapPic(cameraId,savePath,0); 
    } 
} 

然後我用JAVAH生成頭文件:

#include <jni.h> 

#ifndef _Included_CameraCatcher 
#define _Included_CameraCatcher 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  CameraCatcher 
* Method: initCamera 
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J 
*/ 
JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera 
    (JNIEnv *, jobject, jstring, jstring, jstring, jstring); 

/* 
* Class:  CameraCatcher 
* Method: snapPic 
* Signature: (JLjava/lang/String;I)I 
*/ 
JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic 
    (JNIEnv *, jobject, jlong, jstring, jint); 

#ifdef __cplusplus 
} 
#endif 
#endif 

C++代碼:

JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera 
(JNIEnv * env, jobject c, jstring arg_ip, jstring arg_port, jstring arg_username, jstring arg_pwd) 
{ 
    return 1; 
} 
JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic 
(JNIEnv * env, jobject c, jlong arg_id, jstring arg_path, jint arg_no) 
{ 
    return 2; 
} 

我編譯這段代碼,並得到新的DLL。 但是它仍然有誤差之前.......

更新2: Yes.It作品。我不知道爲什麼函數定義代碼在我的.cpp文件中發生了變化。由於EJP昨天告訴我這個問題,我剛剛將jclass更改爲jobject。可能它自昨天以來一直偶然發生變化,我沒有注意到。這全是我的粗心。再次感謝大家。

問題正是EJP所說的。我使用靜態函數生成了該文件,但使其以非靜態方式工作。另一個問題是,當我使用類Test時,我生成了類CameraCatcher。

+0

自從您生成'javah'文件後,您已經將方法從'static'更改。 – EJP

+0

@EJP我還不清楚。你能詳細解釋一下嗎?我該怎麼辦? – lionel

+0

錯誤,重新生成.h文件?並相應地調整你的方法簽名? – EJP

回答

1

我測試了你的代碼。你需要在C編輯功能名稱++,你需要有這樣的事情

#include "test.h" 
    #include <jni.h> 

JNIEXPORT jlong JNICALL Java_CameraCatcher_Test_initCamera 
    (JNIEnv *env, jobject obj, jstring ip, jstring port, jstring username, jstring pwd){ 

    return 1.0; 
} 
JNIEXPORT jint JNICALL Java_CameraCatcher_Test_snapPic 
    (JNIEnv *env, jobject obj, jlong id, jstring savePath, jint no){ 
    return 5; 
} 

不要忘記你的類測試,將其添加在Java_CameraCatcher_Test_snapPic的名稱。

編輯1: 這是我在標題:

/* DO NOT EDIT THIS FILE - it is machine generated */ 
#include <jni.h> 
/* Header for class CameraCatcher */ 

#ifndef _Included_CameraCatcher 
#define _Included_CameraCatcher 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  CameraCatcher 
* Method: initCamera 
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J 
*/ 
JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera 
    (JNIEnv *, jobject, jstring, jstring, jstring, jstring); 

/* 
* Class:  CameraCatcher 
* Method: snapPic 
* Signature: (JLjava/lang/String;I)I 
*/ 
JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic 
    (JNIEnv *, jobject, jlong, jstring, jint); 

#ifdef __cplusplus 
} 
#endif 
#endif 

C++:

#include "cameracatcher.h" 
#include <jni.h> 
#include <stdio.h> 
#include <iostream> 
#include <unistd.h> 
JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera 
    (JNIEnv *env, jobject obj, jstring ip, jstring port, jstring username, jstring pwd){ 

    return 1.0; 
} 
JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic 
    (JNIEnv *env, jobject obj, jlong id, jstring savePath, jint no){ 
    return 5.5; 
} 

的Java:

public class CameraCatcher { 

    public native long initCamera(String ip, String port, String username, String pwd); 

    public native int snapPic(long id, String savePath, int no); 

    static { 
     System.load("/home/tarik/NetBeansProjects/Testc++/dist/test.so"); 
    } 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     CameraCatcher tNative = new CameraCatcher(); 
     String ip = "192.108.1.108"; 
     String port = "37777"; 
     String username = "admin"; 
     String pwd = "123456"; 
     long cameraId = tNative.initCamera(ip, port, username, pwd); 
     System.out.println(cameraId); 
     String savePath = "D:/"; 
     int number = tNative.snapPic(cameraId, savePath, 0); 
     System.out.println(number); 
    } 
} 

一切工作正常。

+0

CameraCatcher是我的課程名稱。我使用默認包。 – lionel

+1

這裏的代碼並非如此。 我推薦你重新生成頭文件,並採用相同的方法名稱及其參數。 –

0

JNI方法名稱需要遵循約定。 可以使用JDK附帶的內置工具生成方法名稱。

請參閱此鏈接瞭解更多詳情。 https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html

+0

方法名稱是自動生成的,我沒有更改它。 – lionel

+0

但是你改變了它生成的源代碼。 – EJP

+0

@EJP我只是填寫了源代碼主要功能的內容。這對它生成的.h文件沒有任何影響。現在,我使用與上述Java代碼相同的代碼來生成頭文件。但它仍然不起作用。也許我不明白你的意思。 – lionel

1

包含本機方法的Java類名爲測試。但是,您生成名爲CameraCatcher的類的C++頭(默認包中)。

您可以重命名Java類,也可以將C++函數更改爲Java_Test_initCameraJava_Test_snapPic。不要忘記將這些函數定義爲extern "C"(我們通常在頭文件中執行此操作,由javah生成)。