2012-07-16 75 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