• 2008-04-01

    JNI初探 - [Java]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://navigating.blogbus.com/logs/18030333.html

    JNI即是Java Native Interface,主要用来Java和其他语言之间的交互,多半是和平台依赖的调用、其他高级语言的库甚至是低级语言交互。相信大家平时在JDK中看到很多native的方法,但是自己写JNI应用的会确很少。这次因为在进行开发中,遇到需要Java调用一个现成的成熟的功能完善的C语言应用库,因此 JNI便成了Java和C库之间的桥的功能。既然是初探,那么下面我们就从HelloWorld开始吧:虽然Java是一个跨平台的语言,但是C语言是一个和平台密切相关的语言;所以针对Unix、Linux、Windows等不同的操作系统,C语言的预编译,动态库的创建等都有一些差别,也需要我们分别进行处理之。下面仅基于Sun的Unix平台Sun Solaris开发为例。
    1.首先声明第一个Java native程序:HelloWorld.java。
    public class HelloWorld {
        static {
            init();
        }

        private native int hello();

        public int sayHello() {
            return hello();
        }

        /**
         * @param args
         */
        public static void main(String[] args) {
            HelloWorld hw = new HelloWorld();
            System.out.println("Say in Java:" + hw.sayHello());
        }

        private static void init() {
            System.out.println("Starting to load HelloWorld lib.");
            try {
                System.loadLibrary("HelloWorld");
            } catch (Throwable t) {
                System.out.println("Load unsuccessfully.");
                t.printStackTrace();
                System.exit(-1);
            }
            System.out.println("Load successfully.");
        }
    }
    2.编译该Java文件。
    javac HelloWorld.java
    3.生成相应的C语言的HelloWorld.h头文件,javah HelloWorld,头文件内容如下:(其中,static Java方法和非static Java方法经过javah -jni生成的C头文件是有区别的,差异在于参数,static Java方法生成的相应的C方法的第二个参数是jclass类型,非static Java方法生成的相应的C方法的第二个参数是jobject类型。)
    more HelloWorld.h
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class HelloWorld */

    #ifndef _Included_HelloWorld
    #define _Included_HelloWorld
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     HelloWorld
     * Method:    hello
     * Signature: ()I
     */
    JNIEXPORT jint JNICALL Java_HelloWorld_hello
      (JNIEnv *, jobject);

    #ifdef __cplusplus
    }
    #endif
    #endif
    4.开始编写第一个c语言的JNI的本地(native)方法:
    vi HelloWorld.c
    #include <jni.h>
    #include "HelloWorld.h"
    #include <stdio.h>

    JNIEXPORT jint JNICALL Java_HelloWorld_hello
    (JNIEnv* env, jobject target)
    {
      printf("Hello World in C program!!!\n");
      return 2;
    }
    5.生成Unix下的动态库.so文件:
    cc -G -I. -I$JAVA_HOME/include -I$JAVA_HOME/include/solaris HelloWorld.c -o libHelloWorld.so
    在当前目录下看到新生成的libHelloWorld.so文件。也许你会注意到我们在Java程序中System.loadLibrary()加载的是库HelloWorld,那么这其实是一个命名的规范而已。以lib开头的.so文件即是Unix下的动态库,而JNI加载器通过HelloWorld这个名字实际上希望加载的动态库是libHelloWorld.so。
    6.设置环境变量,查看LD_LIBRARY_PATH并设置:
    vi .cshrc
    setenv LD_LIBRARY_PATH '.:/usr/local/lib:$LD_LIBRARY_PATH'
    source .cshrc
    这个环境变量设置的是Java的动态库加载器需要加载的C动态库所在的路径。因此,我们生成的libHelloWorld.so一定要在这个环境变量中设置,在这个例子中我就把当前目录.加到环境变量LD_LIBRARY_PATH了:)
    7.执行HelloWorld文件,java HelloWorld,在标准输出上看到:
    Starting to load HelloWorld lib.
    Load successfully.
    Hello World in C program!!!
    Say in Java:2
    一切Okey,如此的easy,一阵狂喜!接下来就是将这个例子运用于JNI的开发之中了。

    Resource:
    Java Native Interface: Programmer's Guide and Specification
    http://java.sun.com/docs/books/jni/html/start.html#27008
    http://linuxmafia.com/faq/Admin/ld-lib-path.html
    https://www6.software.ibm.com/developerworks/cn/education/java/j-jni/tutorial/j-jni-2-15.html

    收藏到:Del.icio.us




    引用地址:

    评论

  • 这里算彻底荒废了。也不知道你是咋想的。咋不更新了呢?