桂林建站平台哪家好,给别人做网站怎么收取费用,温州建设小学网站,兰州建设局网站公告文章目录一、概述二、JNIEnv结构体三、JNINativeInterface结构体3.1 Class操作3.2 反射操作3.3 对象字段 方法操作3.4 类的静态字段 静态方法操作3.5 字符串操作3.6 锁操作3.7 数组操作3.8 注册和反注册native方法3.9 异常Exception操作3.10 引用的操作3.11 其它四…
文章目录一、概述二、JNIEnv结构体三、JNINativeInterface结构体3.1 Class操作3.2 反射操作3.3 对象字段 方法操作3.4 类的静态字段 静态方法操作3.5 字符串操作3.6 锁操作3.7 数组操作3.8 注册和反注册native方法3.9 异常Exception操作3.10 引用的操作3.11 其它四、小结一、概述
JNIEnv(Java Native Interface Environment) 是一个JNI接口指针 (每个线程独有一个 JNIEnv 指针)指向了本地方法的一个函数表该函数表中的每一个成员指向了一个JNI函数本地的方法通过JNI函数来访问JVM中的数据结构详情如下图 关联文章
NDK(一)NDK的集成NDK(二)JNI的数据结构NDK(三)JNIEnv解析NDK(四)Native与Java层互调NDK(五)JNI静态注册与动态注册
参考文章
JNI Functions 官方文档
二、JNIEnv结构体
我们知道 JNI 方法一般都是使用 JNIEnv 去调用而 JNIEnv 又是一个指针所以JNI中有哪些函数只需要找到 JNIEnv 的实现体就可以了。
struct _JNIEnv;
# C中直接使用JNINativeInterface指针进行操作。
typedef const struct JNINativeInterface* C_JNIEnv; #if defined(__cplusplus)
typedef _JNIEnv JNIEnv;从上述代码可以看到C中直接使用 JNINativeInterface 指针进行操作。在C文件中是对_JNIEnv 起的一个别名 JNIEnv。 下面我们来看下 _JNIEnv 结构体的定义。
struct _JNIEnv {/* do not rename this; it does not seem to be entirely opaque */const struct JNINativeInterface* functions;#if defined(__cplusplus)jint GetVersion(){ return functions-GetVersion(this); }jclass DefineClass(const char *name, jobject loader, const jbyte* buf,jsize bufLen){ return functions-DefineClass(this, name, loader, buf, bufLen); }jclass FindClass(const char* name){ return functions-FindClass(this, name); }// ...略
}通过上面的代码可知_JNIEnv 内部所有的操作都是委托给JNINativeInterface指针进行操作的相当于_JNIEnv只是一个代理层。而在C语言中直接使用的是JNINativeInterface指针这就是JNIEnv在C和C调用方式不一致的原因。 三、JNINativeInterface结构体
下面我们来分析一下 JNINativeInterface 的结构体JNINativeInterface 结构体中主要包含如下几类的操作
Class操作反射操作对象字段 方法操作类的静态字段 静态方法操作字符串操作锁操作数组操作注册和反注册native方法异常Exception操作引用的操作
下文中 JNINativeInterface 内的方法有时会省略一些参数信息我们可以通过 JNI Functions 官方文档 来查看函数原型。
以 FindClass 函数为例
struct JNINativeInterface {jclass (*FindClass)(JNIEnv*, const char*);
}// 函数原型为
jclass FindClass(JNIEnv *env, const char *name);详情如下图所示 3.1 Class操作
struct JNINativeInterface {/*获取当前JNI版本信息:*/jint (*GetVersion)(JNIEnv *);// 定义一个类类是从某个字节数组buf中读取出来的jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, jsize);// 查找全限定名为name的类如String类java/lang/Stringjclass (*FindClass)(JNIEnv*, const char*);// 获取当前类的父类通常在使用FindClass获取到类之后再调用这个函数jclass (*GetSuperclass)(JNIEnv*, jclass);
}3.2 反射操作
struct JNINativeInterface {// 将一个Method对象转换为jmethodIDjmethodID (*FromReflectedMethod)(JNIEnv*, jobject);jfieldID (*FromReflectedField)(JNIEnv*, jobject);// 通过jmethodID反射得到Method对象jobject (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);/* spec doesnt show jboolean parameter */jobject (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);
}3.3 对象字段 方法操作
struct JNINativeInterface {// 通过指定jclass类名、字段名称、字段类型来获取jfieldIDjfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);// ---------- 操作Field -------------// 通过类的jobject和jfieldID获取字段的jobject对象。void (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject);jobject (*GetObjectField)(JNIEnv*, jobject, jfieldID);// 8种基本类型字段的获取与赋值。void (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte);jbyte (*GetByteField)(JNIEnv*, jobject, jfieldID);// ---------- 操作Method -------------// 通过指定jclass类名、方法名称、方法签名信息来获取jmethodIDjmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);// 8种基本类型boolean、byte、char、short、int、long、float、double。// ...是可变长度的参数参数类型相同。jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);// va_list是可变长度的参数参数类型可以不同。jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);// jvalue 是8中基本类型jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
}typedef union jvalue {jboolean z;jbyte b;jchar c;jshort s;jint i;jlong j;jfloat f;jdouble d;jobject l;
} jvalue;小结
方法参数通过支持3种不同的参数类型来覆盖所有的参数场景。单个参数场景使用 jvalue 来表示支持一个参数的场景。多个相同参数场景使用 … 来表示支持同类型的多个参数。多个不同参数场景使用 va_list 来表示支持不同类型的多个参数。
3.4 类的静态字段 静态方法操作
struct JNINativeInterface {// ---------- 操作 Static Field ------------- jfieldID (*GetStaticFieldID)(JNIEnv*, jclass, const char*, const char*);void (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject);jobject (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID);void (*SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte);jbyte (*GetStaticByteField)(JNIEnv*, jclass, jfieldID);// ---------- 操作 Static Method -------------// 与GetMethodID方法类似。jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);// 三种参数方式...、va_list、jvalue。jbyte (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);jbyte (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);jbyte (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
}3.5 字符串操作
struct JNINativeInterface {jstring (*NewString)(JNIEnv*, const jchar*, jsize);jsize (*GetStringLength)(JNIEnv*, jstring);const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*);void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*);jstring (*NewStringUTF)(JNIEnv*, const char*);jsize (*GetStringUTFLength)(JNIEnv*, jstring);/* JNI spec says this returns const jbyte*, but thats inconsistent */const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*);void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
}3.6 锁操作
struct JNINativeInterface {jint (*MonitorEnter)(JNIEnv*, jobject);jint (*MonitorExit)(JNIEnv*, jobject);
}3.7 数组操作
struct JNINativeInterface {jbyteArray (*NewByteArray)(JNIEnv*, jsize);jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);void (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray, jbyte*, jint);void (*SetByteArrayRegion)(JNIEnv*, jbyteArray, jsize, jsize, const jbyte*);void (*GetByteArrayRegion)(JNIEnv*, jbyteArray, jsize, jsize, jbyte*);
}3.8 注册和反注册native方法
struct JNINativeInterface {jint (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*, jint);jint (*UnregisterNatives)(JNIEnv*, jclass);
}动态注册JNI代码时会使用 RegisterNatives 函数。具体请参考 - NDK(五)JNI静态注册与动态注册
3.9 异常Exception操作
struct JNINativeInterface {jint (*Throw)(JNIEnv*, jthrowable);jint (*ThrowNew)(JNIEnv *, jclass, const char *);jthrowable (*ExceptionOccurred)(JNIEnv*);void (*ExceptionDescribe)(JNIEnv*);void (*ExceptionClear)(JNIEnv*);void (*FatalError)(JNIEnv*, const char*);
}3.10 引用的操作
struct JNINativeInterface {// 全局变量的创建与删除jobject (*NewGlobalRef)(JNIEnv*, jobject);void (*DeleteGlobalRef)(JNIEnv*, jobject);// 局部变量的创建与删除jobject (*NewLocalRef)(JNIEnv*, jobject);void (*DeleteLocalRef)(JNIEnv*, jobject);// 对象的比较jboolean (*IsSameObject)(JNIEnv*, jobject, jobject);}3.11 其它
struct JNINativeInterface {jint (*GetJavaVM)(JNIEnv*, JavaVM**);jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject);jint (*PushLocalFrame)(JNIEnv*, jint);jobject (*PopLocalFrame)(JNIEnv*, jobject);
}四、小结
JNIEnv 是一个代理实际的操作全部委托给 JNINativeInterface 指针执行。JNINativeInterface 结构体中主要包含如下几类的操作 Class操作反射操作对象字段 方法操作类的静态字段 静态方法操作字符串操作锁操作数组操作注册和反注册native方法异常Exception操作引用的操作