JNI学习

练习java文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.vee.test;

public class HelloJNI {
    static {
        System.loadLibrary("HelloJNI");
    }

    public native void sayHello();

    public static void main(String[] args) {
        new HelloJNI().sayHello();
    }
}

生成头文件

java10以下:

1
2
javac HelloJNI
javah HelloJNI

java10及以上:

1
javac -h include HelloJNI.java

以上命令会在相对地址include目录下生成com_vee_test_HelloJNI.h头文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_vee_test_HelloJNI */

#ifndef _Included_com_vee_test_HelloJNI
#define _Included_com_vee_test_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_vee_test_HelloJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_vee_test_HelloJNI_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

其中最主要的就是函数JNIEXPORT void JNICALL Java_HelloJNI_sayHello (JNIEnv *, jobject);,参数解释如下:

  1. JNIEnv*:JNI运行环境的指针
  2. jobject: 调用对象,指代java中的this对象。

编译出库

linux

1
gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared include/HelloJNI.c -o libs/libHelloJNI.so

运行

1
java -Djava.library.path=./libs com/vee/test/HelloJNI.java

-Djava.library.path是指明java的库路径,如果不加这个选项,则java默认会去系统属性指定的目录下查找动态库文件,找不到会报错:

1
java.lang.UnsatisfiedLinkError: no HelloJNI in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib

可以看到,java会默认从这两个目录中找:

数据类型

基本数据类型

javajnic/c++description
booleanjbooleanunsigned charunsigned 8 bits
bytejbytesigned charsigned 8 bits
charjcharunsigned shortunsigned 16 bits
shortjshortsigned shortsigned 16 bits
intjintsigned intsigned 64 bits
longjlongsigned longsigned 64 bits
floatjfloatfloat32 bits
doublejdoubledouble64bits

注意:这些数据类型是可以在JNI中直接时使用的,不需转换。

引用数据类型

javajni
java.lang.Objectjobject
java.lang.Stringjstring
java.lang.Classjclass
Object[]jobjectArray
boolean[]jbooleanArray
byte[]jbyteArray
char[]jcharArray
short[]jshortArray
int[]jintArray
long[]jlongArray
float[]jfloatArray
double[]jdoubleArray
java.lang.Throwablejthrowable
voidvoid

引用类型不能直接使用,需要经过JNI函数转换才能使用:

1
2
3
jclass intArrayClass = env->FindClass("[I");
int len = 10;
jobjectArray objectIntArray = env->NewObjectArray(len,intArrayClass,NULL);

JNI中所有的array类型,都继承自jarray类型

类描述符

域描述符

JNIENV

JNIEnv,英文全称是Java Native Interface Environment,用咋中国话来说就是Java本地接口环境。

在JNI中,通过native方法编译出的.h文件中对应的函数声明,第一个参数永远是JNIEnv的指针。

JNI中提供了一系列的方式供我们使用:

函数功能
FindClass加载本地定义的类型
GetObjectClass获取对象的类型
NewGlobalRef创建obj参数所引用对象的新全局引用
NewObject构造新的java对象
NewString利用Unicode字符数组构造新的java.lang.String对象
NewArray创建类型为Type的数组对象
GetField获取类型为Type的字段
SetField设置类型为Type的字段
GetStaticField获取类型为Type的static的字段的值
SetStaticField设置类型为Type的static的字段的值
CallMethod调用返回类型为Type的方法
CallStaticMethod调用返回值类型为Type的static方法

先到这里,待续。。。