前言
对于任何一个初学者,学习JNI都是从Java和C/C++之间如何传递数据,以及数据类型之间是如何相互映射开始。
Native方法和C函数原型
看点代码
package com.net168.xxx
class Simple {
private native String testA(String str);
private native static void testA(int num);
}
//C端源码
JNIEXPORT jstring JNICALL
Java_Com_net168_xxx_Simple_testA(JNIEnv *env, jobject thiz, jstring str);
JNIEXPORT void JNICALL
Java_Com_net168_xxx_Simple_testB(JNIEnv *env, jclass clz, jint num);
知识点
- C函数方法格式:
JNIEXPORT 返回类型 JNICALL Java_包名_方法名(JNIEnv *env, jobect/jclass thiz, 入参列表)
- 本地方法存在重载情况时,会有双下划线"__",后面跟着参数描述符,也就是长函数名;VM连接优先链接短函数名,然后链接长函数名,如果存在两个重载的本地方法,则只会链接长函数名。
- 链接函数还可以通过JNI的
RegisterNatives
来注册与一个类关联的本地方法。 JNIEXPORT
和JNICALL
是定义在jni.h
里面的两个宏,用来确保函数在本地库外可见,C编译时会进行正确转换。JNIEnv
是一个接口指针,指向若干个函数表,提供了JNI函数帮助C函数访问JVM里面的数据结构。- 本地方法是静态方法时,C函数的第二个变量是jclass,代表本地方法所在的类;如果是一个实例方法时,其变量的类型是jobject,代表本地方法所在的对象实例。
类型映射
本地方法声明中的参数类型在C语言中都有对应的类型,具体对应表格如下:
java类型 | 本地类型 | 描述 |
---|---|---|
boolean | jboolean | C/C++8位整型 |
byte | jbyte | C/C++带符号的8位整型 |
char | jchar | C/C++无符号的16位整型 |
short | jshort | C/C++带符号的16位整型 |
int | jint | C/C++带符号的32位整型 |
long | jlong | C/C++带符号的64位整型e |
float | jfloat | C/C++32位浮点型 |
double | jdouble | C/C++64位浮点型 |
Object | jobject | 任何Java对象,或者没有对应java类型的对象 |
Class | jclass | Class对象 |
String | jstring | 字符串对象 |
Object[] | jobjectArray | 任何对象的数组 |
boolean[] | jbooleanArray | 布尔型数组 |
byte[] | jbyte |