代码之家  ›  专栏  ›  技术社区  ›  user4691169

Java JNA调用不会运行本机代码,导致应用程序停止

  •  2
  • user4691169  · 技术社区  · 9 年前

    我使用JNA(Java Native Access)从Java调用本机方法到C。本机方法(int funcServer(int param1))是一个基本的unix套接字侦听。但不管我是否做了优化的JNA Direct Mapping Interface Mapping ,JNA在我身上熄火了。本地代码即使在函数调用的第一行也不会打印任何内容,但没有抛出异常。

    参见我的最低可行Java示例(在NetBeans IDE产品版本:8.0.2 Build 201411181905和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/libViableExaampleNative.s0的InputStream):

    $ 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)失败了。

    1 回复  |  直到 9 年前
        1
  •  1
  •   WillShackleford    9 年前

    尝试在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
    

    但在Netbeans中运行程序时运行telnet会产生以下结果:

    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Tue Aug  4 19:46:38 2015
    Connection closed by foreign host.