Java JNA 调用不会 运行 本机代码,导致应用程序停止
Java JNA call will not run native code, causes application to stall
我正在使用 JNA (Java Native Access) 调用从 Java 到 C 的本地方法。本地方法 (int funcServer(int param1)) 是一个基本的 unix 套接字监听.但是不管我是否做优化的 JNA Direct Mapping or the Interface Mapping,JNA 都在我身上停滞不前。即使在函数调用的第一行,本机代码也不会打印任何内容,但不会引发异常。
查看我的最小可行 Java 示例(运行 on NetBeans IDE 产品版本:8.0.2 Build 201411181905 with Ubuntu Linux):
package viableexamplejava;
import com.sun.jna.*; // link jna-4.1.0.jar, jna-platform-4.1.0.jar
/**
* Test on Ubuntu Linux or with Cygwin on Windows 7.
*/
public class ViableExample {
/**
* This library depends on Unix Sockets.
*/
public interface NativeLibary extends Library {
public int funcServer(int param1);
}
//uncomment for Indirect Mapping
//private static final NativeLibary myNativeLibrary_;
public static native int funcServer(int param1);
static {
final String windowsLibraryName = "ViableExample.dll";
final String linuxLibraryName = "libViableExampleNative.so"; // compiled with Netbeans
if (Platform.isWindows()) {
System.err.println("Loading Windows dll. 'cygwin1.dll' should be in same directory.");
//myNativeLibrary_ = (NativeLibary) Native.loadLibrary(windowsLibraryName, NativeLibary.class);
Native.register(windowsLibraryName);
} else {
System.err.println("Loading Linux .so");
//myNativeLibrary_ = (NativeLibary) Native.loadLibrary(linuxLibraryName, NativeLibary.class);
Native.register(linuxLibraryName);
}
}
public static void main(String[] args) {
System.err.println("Hello World from Java");
//uncomment for Indirect Mapping
//myNativeLibrary_.funcServer(7);
funcServer(7); // This never prints.
}
}
/**
* Side notes: If the dynamic library cannot be found, this error occurs:
*
* Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load
* library 'libViableExampleNative.so': Native library
* (linux-x86-64/libViableExampleNative.so) not found in resource path
* ([file:/home/user/Desktop/Dropbox/jna-4.1.0.jar,
* file:/home/user/Desktop/Dropbox/jna-platform-4.1.0.jar,
* file:/home/user/NetBeansProjects/ViableExampleJava/build/classes/])
*
* at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:271) at
* com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:398) at
* com.sun.jna.Library$Handler.<init>(Library.java:147) at
* com.sun.jna.Native.loadLibrary(Native.java:412) at
* com.sun.jna.Native.loadLibrary(Native.java:391) at
* viableexamplejava.ViableExample.<clinit>(ViableExample.java:29) Java Result:
* 1
*
* If this happens, you have to put libViableExample.so into the resource path,
* in my case into:
* /home/user/NetBeansProjects/ViableExampleJava/build/classes/
*
* Once it's in there, "Hello World from Java" prints, but nothing else gets
* printed. "myNativeLibrary_.funcServer(7);" doesn't print anything.
*
* Output:
* Loading Linux .so
* Hello World from Java
* (The application does not terminate or throw an exception).
*/
这是我使用的 C 代码:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
/**
* Unix server that sends clients the date and time.
* Compiled with -shared -std=c99.
* Produces "libViableExampleNative.so" when built with Netbeans on Linux.
*/
int funcServer(int param1) {
printf("\n Hello World from C. This is a Socket Server Example Program \n");
printf("\n param1: %d \n", param1);
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
// Just verifying that the C code is running.
printf("I made it to line %d in file %s\n", __LINE__, __FILE__);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof (serv_addr));
memset(sendBuff, '0', sizeof (sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*) &serv_addr, sizeof (serv_addr));
printf("I made it to line %d in file %s\n", __LINE__, __FILE__);
listen(listenfd, 10);
while (1) {
connfd = accept(listenfd, (struct sockaddr*) NULL, NULL);
ticks = time(NULL);
snprintf(sendBuff, sizeof (sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
return 0;
}
更新 1
尝试将 .so 放入 jar 文件中,然后 运行 从终端将其打开(UnsatisfiedLinkError:无法加载库 'libViableExampleNative.so':无法为 linux-x86-64/libViableExampleNative 获取 InputStream .so):
$ zip ./ViableExampleJava.jar ./libViableExampleNative.so
adding: libViableExampleNative.so (deflated 73%)
~/NetBeansProjects/ViableExampleJava/dist$ java -jar ./ViableExampleJava.jar
Loading Linux .so
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'libViableExampleNative.so': Can't obtain InputStream for linux-x86-64/libViableExampleNative.so
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:271)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:398)
at com.sun.jna.Native.register(Native.java:1396)
at com.sun.jna.Native.register(Native.java:1156)
at viableexamplejava.ViableExample.<clinit>(ViableExample.java:33)
* 更新 2 *
已尝试设置系统 属性 "jna.library.path"
当 运行 来自终端(不是 Netbeans)时的正确输出:
// Set jnaPath to: /home/user/NetBeansProjects/ViableExampleNative/dist/Debug/GNU-Linux-x86
$ java -jar ./ViableExampleJava.jar
Hello World from Java
Hello World from C. This is a Socket Server Example Program
param1: 7
I made it to line 26 in file ../../Desktop/Dropbox/ViableExample/native/ViableExample.c
I made it to line 37 in file ../../Desktop/Dropbox/ViableExample/native/ViableExample.c
* 更新 3 *
尽管它可以在 Ubuntu Linux 终端上运行,但我的 Windows 版本(使用 Cygwin)失败了。
在 Netbeans 之外尝试 运行。
当我在 netbeans 中 运行 时,我看到的最后一件事是:
Loading Linux .so
Hello World from Java
当我从终端 运行 使用 :
java -jar target/mavenproject5-1.0-SNAPSHOT.jar
Loading Linux .so
Hello World from Java
Hello World from C. This is a Socket Server Example Program
param1: 7
I made it to line 27 in file newfile.c
I made it to line 38 in file newfile.c
该程序在 Netbeans 中似乎仍然是 运行,但未显示 C 打印输出。我可以判断,因为当根本没有 运行 时,telnet 会显示:
telnet localhost 5000
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
但是 运行 telnet 当程序在 Netbeans 中 运行 时会产生这个:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Tue Aug 4 19:46:38 2015
Connection closed by foreign host.
我正在使用 JNA (Java Native Access) 调用从 Java 到 C 的本地方法。本地方法 (int funcServer(int param1)) 是一个基本的 unix 套接字监听.但是不管我是否做优化的 JNA Direct Mapping or the Interface Mapping,JNA 都在我身上停滞不前。即使在函数调用的第一行,本机代码也不会打印任何内容,但不会引发异常。
查看我的最小可行 Java 示例(运行 on NetBeans IDE 产品版本:8.0.2 Build 201411181905 with Ubuntu Linux):
package viableexamplejava;
import com.sun.jna.*; // link jna-4.1.0.jar, jna-platform-4.1.0.jar
/**
* Test on Ubuntu Linux or with Cygwin on Windows 7.
*/
public class ViableExample {
/**
* This library depends on Unix Sockets.
*/
public interface NativeLibary extends Library {
public int funcServer(int param1);
}
//uncomment for Indirect Mapping
//private static final NativeLibary myNativeLibrary_;
public static native int funcServer(int param1);
static {
final String windowsLibraryName = "ViableExample.dll";
final String linuxLibraryName = "libViableExampleNative.so"; // compiled with Netbeans
if (Platform.isWindows()) {
System.err.println("Loading Windows dll. 'cygwin1.dll' should be in same directory.");
//myNativeLibrary_ = (NativeLibary) Native.loadLibrary(windowsLibraryName, NativeLibary.class);
Native.register(windowsLibraryName);
} else {
System.err.println("Loading Linux .so");
//myNativeLibrary_ = (NativeLibary) Native.loadLibrary(linuxLibraryName, NativeLibary.class);
Native.register(linuxLibraryName);
}
}
public static void main(String[] args) {
System.err.println("Hello World from Java");
//uncomment for Indirect Mapping
//myNativeLibrary_.funcServer(7);
funcServer(7); // This never prints.
}
}
/**
* Side notes: If the dynamic library cannot be found, this error occurs:
*
* Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load
* library 'libViableExampleNative.so': Native library
* (linux-x86-64/libViableExampleNative.so) not found in resource path
* ([file:/home/user/Desktop/Dropbox/jna-4.1.0.jar,
* file:/home/user/Desktop/Dropbox/jna-platform-4.1.0.jar,
* file:/home/user/NetBeansProjects/ViableExampleJava/build/classes/])
*
* at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:271) at
* com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:398) at
* com.sun.jna.Library$Handler.<init>(Library.java:147) at
* com.sun.jna.Native.loadLibrary(Native.java:412) at
* com.sun.jna.Native.loadLibrary(Native.java:391) at
* viableexamplejava.ViableExample.<clinit>(ViableExample.java:29) Java Result:
* 1
*
* If this happens, you have to put libViableExample.so into the resource path,
* in my case into:
* /home/user/NetBeansProjects/ViableExampleJava/build/classes/
*
* Once it's in there, "Hello World from Java" prints, but nothing else gets
* printed. "myNativeLibrary_.funcServer(7);" doesn't print anything.
*
* Output:
* Loading Linux .so
* Hello World from Java
* (The application does not terminate or throw an exception).
*/
这是我使用的 C 代码:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
/**
* Unix server that sends clients the date and time.
* Compiled with -shared -std=c99.
* Produces "libViableExampleNative.so" when built with Netbeans on Linux.
*/
int funcServer(int param1) {
printf("\n Hello World from C. This is a Socket Server Example Program \n");
printf("\n param1: %d \n", param1);
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
// Just verifying that the C code is running.
printf("I made it to line %d in file %s\n", __LINE__, __FILE__);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof (serv_addr));
memset(sendBuff, '0', sizeof (sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*) &serv_addr, sizeof (serv_addr));
printf("I made it to line %d in file %s\n", __LINE__, __FILE__);
listen(listenfd, 10);
while (1) {
connfd = accept(listenfd, (struct sockaddr*) NULL, NULL);
ticks = time(NULL);
snprintf(sendBuff, sizeof (sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
return 0;
}
更新 1
尝试将 .so 放入 jar 文件中,然后 运行 从终端将其打开(UnsatisfiedLinkError:无法加载库 'libViableExampleNative.so':无法为 linux-x86-64/libViableExampleNative 获取 InputStream .so):
$ zip ./ViableExampleJava.jar ./libViableExampleNative.so
adding: libViableExampleNative.so (deflated 73%)
~/NetBeansProjects/ViableExampleJava/dist$ java -jar ./ViableExampleJava.jar
Loading Linux .so
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'libViableExampleNative.so': Can't obtain InputStream for linux-x86-64/libViableExampleNative.so
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:271)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:398)
at com.sun.jna.Native.register(Native.java:1396)
at com.sun.jna.Native.register(Native.java:1156)
at viableexamplejava.ViableExample.<clinit>(ViableExample.java:33)
* 更新 2 *
已尝试设置系统 属性 "jna.library.path"
当 运行 来自终端(不是 Netbeans)时的正确输出:
// Set jnaPath to: /home/user/NetBeansProjects/ViableExampleNative/dist/Debug/GNU-Linux-x86
$ java -jar ./ViableExampleJava.jar
Hello World from Java
Hello World from C. This is a Socket Server Example Program
param1: 7
I made it to line 26 in file ../../Desktop/Dropbox/ViableExample/native/ViableExample.c
I made it to line 37 in file ../../Desktop/Dropbox/ViableExample/native/ViableExample.c
* 更新 3 *
尽管它可以在 Ubuntu Linux 终端上运行,但我的 Windows 版本(使用 Cygwin)失败了。
在 Netbeans 之外尝试 运行。
当我在 netbeans 中 运行 时,我看到的最后一件事是:
Loading Linux .so
Hello World from Java
当我从终端 运行 使用 :
java -jar target/mavenproject5-1.0-SNAPSHOT.jar
Loading Linux .so
Hello World from Java
Hello World from C. This is a Socket Server Example Program
param1: 7
I made it to line 27 in file newfile.c
I made it to line 38 in file newfile.c
该程序在 Netbeans 中似乎仍然是 运行,但未显示 C 打印输出。我可以判断,因为当根本没有 运行 时,telnet 会显示:
telnet localhost 5000
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
但是 运行 telnet 当程序在 Netbeans 中 运行 时会产生这个:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Tue Aug 4 19:46:38 2015
Connection closed by foreign host.