JNI学习

来源:互联网 发布:淘宝虚拟男朋友 编辑:程序博客网 时间:2024/05/29 08:09

2.1 Overview

 write a simple Java application that calls a C function to print “Hello World!”. The pro-

cess consists of the following steps:
          1. Create a class (HelloWorld.java) that declares the native method.
          2. Use javac to compile the HelloWorld source file, resulting in the class file
              HelloWorld.class. The javac compiler is supplied with JDK or Java 2 SDK releases.
          3. Use javah -jni to generate a C header file (HelloWorld.h) containing the
              function prototype for the native method implementation. The javah tool is
              provided with JDK or Java 2 SDK releases.
          4. Write the C implementation (HelloWorld.c) of the native method.
          5. Compile the C implementation into a native library, creating HelloWorld.dll
               or libHelloWorld.so. Use the C compiler and linker available on the host environment.
          6. Run the HelloWorld program using the java runtime interpreter. Both the
              class file (HelloWorld.class) and the native library (HelloWorld.dll or libHelloWorld.so) are loaded at runtime.

              The remainder of this chapter explains these steps in detail.

觉得挺好,翻译一下啊:

      写一个java应用,调用c函数打印“Hello World”,整个过程又一下几步组成:

         1、创建一个类(HelloWorld.java),并在该类中声明native方法,即本地方法。

         2、使用javac编译这个源文件,生成字节码文件HelloWorld.class,这个编译器在jdk或java2SDK以上都支持

         3、使用javah -jni 生成一个C头文件,HelloWorld.h,这个文件中包含了这些c函数原型本地方法实现,其实就是声明c函数

         4、写一个本地方法的用C语言实现的HelloWorld.c

         5、使用主机上可用的C编译器和连接器,编译C的成为一个本地库,创建为HelloWorld.dll(windows),或者libHelloWorld.so(linux)

         6、用java运行时解析器运行HelloWorld程序,HelloWorld.class和本地库HelloWorld.dll获libHelloWorld.so都被加载到运行时虚拟机了


我看的是这本书,《The JavaTM Native Interface》  Programmer’s Guide and Specification,听不错的

      

       HelloWorld小例子

       1、写HelloWorld.java

        

class HelloWorld {private native void print();public static void main(String[] args) {new HelloWorld().print();}static {System.loadLibrary("HelloWorld");}}
       2、编译生成字节码文件  

       命令:javac HelloWorld.java ->生成了HelloWorld.class

       编译生成本地调用头文件HelloWorld.h

       命令:javah -jni HelloWorld

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloWorld */#ifndef _Included_HelloWorld#define _Included_HelloWorld#ifdef __cplusplusextern "C" {#endif/* * Class:     HelloWorld * Method:    print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif


       3、编写HelloWorld.c

#include <jni.h>#include <stdio.h>#include "HelloWorld.h"JNIEXPORT void JNICALLJava_HelloWorld_print(JNIEnv *env, jobject obj){printf("Hello World!\n");return;}

       4、编译生成动态连接库-> libHelloWorld.so

       命令:    gcc -shared -I /usr/lib/jvm/jdk1.7/include/  -I /usr/lib/jvm/jdk1.7/include/linux/ HelloWorld.c -o libHelloWorld.so
                 

                    -shared 指明是生成动态连接库
                    -I (小写字母i的大写)是生成此目标文件需要导入的库(缩写为import)
                        其中jni.h在/usr/lib/jvm/jdk1.7/include/ 下
                     jni.h中又包含了jni_md.h,文件在/usr/lib/jvm/jdk1.7/include/linux/下

                     HelloWorld.c指明要编译的c文件

                     -o 指明要生成的目标文件

        注意:不要在HelloWorld.c前加-c这样编译出来的文件就是可执行文件了,而不是动态连接库

       5、在java虚拟机上运行

       命令:java HelloWorld,会报错,如下:

~/test/jni$ java HelloWorldException in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.pathat java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)at java.lang.Runtime.loadLibrary0(Runtime.java:845)at java.lang.System.loadLibrary(System.java:1084)at HelloWorld.<clinit>(HelloWorld.java:8)

     这是因为没有指定动态连接库的路径,java本地调用库的路径可以这样,

       命令:export LD_LIBRARY_PATH=.

      这表示把当前路径加入库中

      再此运行:

      命令:java HelloWorld

~/test/jni$ java HelloWorldHello World!