2012-07-16 71 views
1

我爲C++ BSD套接字客戶端運行基本的Java包裝。我可以編譯Java並生成一個頭文件,但是當我嘗試運行它時,它會返回Exception in thread "main" java.lang.UnsatisfiedLinkError: JavaClient.socketComm()V本地方法上的JNI UnsatisfiedLinkError

從我所能找到的內容看來,這似乎表示方法簽名之間不匹配,但我找不到任何錯誤。

Java代碼的

public class JavaClient 
{ 
    public native void socketComm(); 

    public static void main(String[] args) 
    { 
     System.load("/home/cougar/workspace/ArbiterBSDSocketComms/JNIClient/JavaClient.so"); 
     JavaClient client = new JavaClient(); 
     client.socketComm(); 

     System.out.println("Done"); 
    } 
} 

C實現

#include <iostream> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <unistd.h> 
#include <errno.h> 
#include <cstdlib> 
#include <stdio.h> 
#include <jni.h> 
#include "JavaClient.h" 
#define MAXHOSTNAME 256 

JNIEXPORT void JNICALL Java_JavaClient_socketComm 
    (JNIEnv *env, jobject obj) { 
    struct sockaddr_in remoteSocketInfo; 
    struct hostent *hPtr; 
    int socketHandle; 
    char *remoteHost="localhost"; 
    int portNumber = 8080; 

memset(&remoteSocketInfo, 0, sizeof(struct sockaddr_in));  //Clear structure memory 

if ((hPtr = gethostbyname(remoteHost)) == NULL)    //Get sysinfo 
{ 
    printf("System DNS resolution misconfigured."); 
    printf("Error number: ", ECONNREFUSED); 
    exit(EXIT_FAILURE); 
} 

if((socketHandle = socket(AF_INET, SOCK_STREAM, 0)) < 0)  //Create socket 
{ 
    close(socketHandle); 
    exit(EXIT_FAILURE); 
} 

memcpy((char *)&remoteSocketInfo.sin_addr, 
     hPtr->h_addr, hPtr->h_length);       //Load sys info into sock data structures 
remoteSocketInfo.sin_family = AF_INET; 
remoteSocketInfo.sin_port = htons((u_short)portNumber);   //Set port number 

if(connect(socketHandle, (struct sockaddr *)&remoteSocketInfo, sizeof(struct sockaddr_in)) < 0) 
{ 
    close(socketHandle); 
    exit(EXIT_FAILURE); 
} 

int rc=0; 
char buf[512]; 

strcpy(buf, "Sup server"); 
send(socketHandle, buf, strlen(buf)+1, 0); 
} 

void main(){} 

頭文件

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

#ifndef _Included_JavaClient 
#define _Included_JavaClient 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  JavaClient 
* Method: socketComm 
* Signature:()V 
*/ 
JNIEXPORT void JNICALL Java_JavaClient_socketComm 
    (JNIEnv *, jobject); 

#ifdef __cplusplus 
} 
#endif 
#endif 

藉口一些不好的格式,我沒有用太多計算器和代碼格式化有點粗略。

這些文件都位於/ JNIClient中。

我正在運行Ubuntu 12.04 x64,並且我安裝了32位和64位JDK。我試圖用32位版本生成.so,這本來是理想的,但我得到了一個ELF不匹配,所以我只用64位,所以我不必處理這個問題。 (。上任何見解是值得歡迎的爲好)

我的過程是:

$>javac JavaClient.java

$>javah JavaClient

$>cc -m64 -g -I/usr/lib/jvm/java-6-openjdk-amd64/include -I/usr/lib/jvm/java-6-openjdk-amd64/include/linux -shared JavaClient.c -o JavaClient.so

$>java JavaClient

完整的錯誤消息是

Exception in thread "main" java.lang.UnsatisfiedLinkError: JavaClient.socketComm()V 
    at JavaClient.socketComm(Native Method) 
    at JavaClient.main(JavaClient.java:9) 

$>nm JavaClient.so回報:

[email protected]:~/workspace/ArbiterBSDSocketComms/JNIClient$ nm JavaClient.so 
0000000000200e50 a _DYNAMIC 
0000000000200fe8 a _GLOBAL_OFFSET_TABLE_ 
      w _Jv_RegisterClasses 
0000000000200e30 d __CTOR_END__ 
0000000000200e28 d __CTOR_LIST__ 
0000000000200e40 d __DTOR_END__ 
0000000000200e38 d __DTOR_LIST__ 
00000000000005e0 r __FRAME_END__ 
0000000000200e48 d __JCR_END__ 
0000000000200e48 d __JCR_LIST__ 
0000000000201010 A __bss_start 
       w [email protected]@GLIBC_2.2.5 
0000000000000540 t __do_global_ctors_aux 
0000000000000490 t __do_global_dtors_aux 
0000000000201008 d __dso_handle 
       w __gmon_start__ 
0000000000201010 A _edata 
0000000000201020 A _end 
0000000000000578 T _fini 
0000000000000438 T _init 
0000000000000470 t call_gmon_start 
0000000000201010 b completed.6531 
0000000000201018 b dtor_idx.6533 
0000000000000510 t frame_dummy 

編輯:我有一個理論,即。所以正在興建不當,如$>nm JavaClient.so不顯示在它的方法名。有關cc命令有什麼問題的任何建議?

好吧,SO:我一直在這,因爲沒有什麼看起來不錯。方法簽名全部匹配,沒有什麼應該是錯誤的,eclipse文件屬性表示它正在編輯正確的文件等等等等。我終於捕獲了JavaClient.c,並且它是空白的。顯然,eclipse並非真正編輯它所說的文件。修正了,現在一切都很好。

+0

郵政'nm'輸出 – 2012-07-16 21:21:03

+0

NM輸出增加,你可以看到有一個在。所以到socketComm沒有提及。我不知道爲什麼 – 2012-07-16 21:26:21

+1

請不要將標題改爲[已解決]。相反,直接回答你的問題,然後接受你的答案。這使得未來的訪問者更容易找到你的問題的答案。 – templatetypedef 2012-07-16 22:59:41

回答

0

我一直在這,因爲沒有什麼看起來不錯。方法簽名全部匹配,沒有什麼應該是錯誤的,eclipse文件屬性表示它正在編輯正確的文件等等等等。我終於捕獲了JavaClient。c,它是空白的。顯然,eclipse並非真正編輯它所說的文件。修正了,現在一切都很好。

不知道爲什麼Eclipse中聲稱要編輯一個空白文件,我檢查和複查,並沒有引用任何鏈接或任何東西,但如果你有同樣的問題,因爲我檢查出來。

0

我會給你一個更好的解決方案。

public void socketComm() throws IOException 
{ 
    Socket socket = new Socket("localhost", 8080); 
    try 
    { 
    socket.getOutputStream().write("Sup server\u0000".getBytes()); 
    } 
    finally 
    { 
    socket.close(); // You forgot this 
    } 
} 

根本不需要JNI。它也不會關閉無效句柄,如果socket()返回< 0,與您的代碼不同。

+0

我知道我可以在Java :)這是怎麼回事的軟件全部用C++編寫,這是我們都希望用一個類來處理插座完全是另外一個套件一起使用手柄插口,而不是用C++和Java中的一個。 – 2012-07-17 18:51:24