首页 > 代码库 > 虚拟机下的JNI

虚拟机下的JNI

      对于别人写的linux下的jni写的真的不清晰、明了,甚至会出现错误;对于代码重点的就是不会的人用你的代码就可以执行就ok了!!好了,废话不说了,来开始咱们的jni了;

    首先咱们得理解一下jni的概念吧: jni(java native interface)java原生接口;对于学习过java的我们并不陌生接口的概念吧,接口就是定义一系列的方法,让其实现类来实现;好了,咱们直接上代码,用代码来解决一切;

    第一个程序:对于java类的属性赋值:

        首先看看完成后的文件:

         

    首先新建TestInt.java :  

public class TestInt{

      public native void setInt(int a);
      public native int getInt();
      static{
           System.loadLibrary("TestInt");
          }
      public static void main(String args[]){
          
          TestInt testInt = new TestInt();
          testInt.setInt(5);
          System.out.println("你要输出的值为:"+testInt.getInt()); 
       }
}

 

  然后进行编译:javac TestInt.java 生成TestInt.class计算机可以读取的二进制文件,依靠此二进制文件生成头文件 TestInt.h

     指令为:javah -jni TestInt  生成了TestInt.h文件:其代码如下:

 

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestInt */

#ifndef _Included_TestInt
#define _Included_TestInt
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     TestInt
 * Method:    setInt
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_TestInt_setInt
  (JNIEnv *, jobject, jint);

/*
 * Class:     TestInt
 * Method:    getInt
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_TestInt_getInt
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

 

咱们可以看到这里有两个方法分别如上图代码所示:

 咱们要在写一个c语言代码,来实现对于其方法的实现:说白了,其方法就是接口中要实现的方法:新建一个TestInt.cpp

#include<jni.h>
#include"TestInt.h"

int b;
JNIEXPORT void JNICALL Java_TestInt_setInt
  (JNIEnv *env, jobject obj, jint a){
      b=3+a;
  } 

JNIEXPORT jint JNICALL Java_TestInt_getInt
  (JNIEnv * env, jobject obj){
      return b;
}

ok!以上代码已经完成,接下来就是要生成动态库了:

          g++ -I/usr/java/jdk1.6.0_43/include/linux -I/usr/java/jdk1.6.0_43/include -fpic -shared -o libTestInt.so TestInt.cpp

  如果你要是这样写:   g++  -fpic -shared -o libTestInt.so TestInt.cpp会抛出如下异常: 

TestInt.cpp:1:16: 错误:jni.h:没有那个文件或目录
TestInt.h:15: 错误:expected constructor, destructor, or type conversion before ‘void’
TestInt.h:23: 错误:‘JNIEXPORT’ 没有命名一个类型
TestInt.cpp:5: 错误:expected constructor, destructor, or type conversion before ‘void’
TestInt.cpp:10: 错误:‘JNIEXPORT’ 没有命名一个类型

所以必须要指明jdk的头文件的路径,以及include目录下其他资源文件的路径;

最后一条指令:java Djava.dictionary.path=. TestInt

  输出结果:你要输出的值为:8

 

 另外一个程序:关于无返回值字符串的输出程序:

    首先也一样将结果目录图片显示出来:

    

 我也不那么多废话了:直接将各个文件的代码复制到页面:

public class TestJni{

    public native void print(String context);
     
      static{
                 System.loadLibrary("TestJni");   
           }
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestJni */

#ifndef _Included_TestJni
#define _Included_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     TestJni
 * Method:    print
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_TestJni_print
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
#include <jni.h>
#include  "TestJni.h"
JNIEXPORT void JNICALL Java_TestJni_print
  (JNIEnv *env, jobject obj, jstring content){
   
     const jbyte *str=( const jbyte *)(*env)->GetStringUTFChars(env,content,JNI_FALSE);
      printf("Hello,%s\n",str);
   (*env)->ReleaseStringUTFChars(env, content, (const char *)str );
  }
public class HelloWorld{
   
   public static void main(String args[]){
         
        new HelloWorld();
    }
   public HelloWorld(){
       new TestJni().print("yuchao");
    }
}

各个操作过程第一个程序写的很清楚了,所以这里我就不写了;