赞
踩
JNI 中有许多和 Java 相对应的类型
Java 类型 | JNI 类型 |
---|---|
boolean | jboolean |
byte | jbyte |
char | jchar |
short | jshort |
int | jint |
long | jlong |
float | jfloat |
double | jdouble |
void | void |
java.lang.Class | jclass |
java.lang.String | jstring |
java.lang.Throwable | jthrowable |
object | jobject |
object[] | jobjectarray |
boolean[] | jbooleanarray |
byte[] | jbytearray |
char[] | jchararray |
short[] | jshortarray |
int[] | jintarray |
long[] | jlongarray |
float[] | jfloatarray |
double[] | jdoublearray |
Java 类型 | JNI 类型签名 |
---|---|
void | V |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | J |
float | F |
double | D |
L fully-qualified-class ; | fully-qualified-class |
type[] | [ type |
method type | ( arg-types ) ret-type |
例如,下面的 Java 方法:
public long foo(int n, String s, int[] arr)
在 JNI 中的签名如下:
(ILjava/lang/String;[I)J
JNI 定义了八种 Java 基本类型,其余的 jobject、jclass、jarray、jxxxArray、jstring 等都是引用类型。
JNI 的引用有两层含义:
但是如果引用被 JVM 释放了,指针仍然指向一个地址,只是对应的地址中数据已经被释放了
JNI 的引用分为四种:
全局引用(GlobalReferences):全局有效。JVM 无法释放回收,必须通过调用 DeleteGlobalRef() 显式释放。
创建全局引用:jobject NewGlobalRef(JNIEnv *env, jobject obj);
释放全局引用:void DeleteGlobalRef(JNIEnv *env, jobject globalRef);
弱全局引用(WeakGlobalReferences):一种特殊的全局引用,可以被 JVM 回收。
创建弱全局引用:jobject NewWeakGlobalRef(JNIEnv *env, jobject obj);
释放弱全局引用:void DeleteWeakGlobalRef(JNIEnv *env, jobject globalRef);
局部引用(LocalReferences):在方法内创建,方法结束后自动释放。虽然会在方法结束后自动释放,但是如果消耗过多 JVM 资源,也可以手动释放。
创建局部引用:jobject NewLocalRef(JNIEnv *env, jobject obj);
释放局部引用:void DeleteLocalRef(JNIEnv *env, jobject globalRef);
虽然方法结束会自动释放,但是建议使用完了就手动释放。尤其以下两种情况必须手动释放:
哪些场景需要释放?JNI 函数内部创建的 jobject、jclass、jstring、jarray 等引用都需要释放。
无效引用(InvalidReferences):无效引用一般情况下没有什么用,不展开介绍。
jfieldID 和 jmethodID 是常规的 C 指针类型,它们的声明如下:
struct _jfieldID; /* opaque structure */
typedef struct _jfieldID *jfieldID; /* field IDs */
struct _jmethodID; /* opaque structure */
typedef struct _jmethodID *jmethodID; /* method IDs */
GetFieldID / GetXxxField / SetXxxField
GetStaticFieldID / GetStaticXxxField / SetStaticXxxField
/* * @param env: JN I接口指针。 * @param clazz:一个 Java 类。 * @param name:字段名称,以 \0 结尾的 UTF-8 字符串。 * @param sig:字段签名,以 \0 结尾的 UTF-8 字符串。 * @return 返回字段 ID,如果操作失败返回 NULL。 */ jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig); // 获取静态字段 jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig); jobject GetObjectField(JNIEnv*, jobject, jfieldID); jboolean GetBooleanField(JNIEnv*, jobject, jfieldID); jbyte GetByteField(JNIEnv*, jobject, jfieldID); jchar GetCharField(JNIEnv*, jobject, jfieldID); jshort GetShortField(JNIEnv*, jobject, jfieldID); jint GetIntField(JNIEnv*, jobject, jfieldID); jlong GetLongField(JNIEnv*, jobject, jfieldID); jfloat GetFloatField(JNIEnv*, jobject, jfieldID); jdouble GetDoubleField(JNIEnv*, jobject, jfieldID); // 获取静态字段值 jobject GetStaticObjectField(JNIEnv*, jclass, jfieldID); jboolean GetStaticBooleanField(JNIEnv*, jclass, jfieldID); jbyte GetStaticByteField(JNIEnv*, jclass, jfieldID); jchar GetStaticCharField(JNIEnv*, jclass, jfieldID); jshort GetStaticShortField(JNIEnv*, jclass, jfieldID); jint GetStaticIntField(JNIEnv*, jclass, jfieldID); jlong GetStaticLongField(JNIEnv*, jclass, jfieldID); jfloat GetStaticFloatField(JNIEnv*, jclass, jfieldID); jdouble GetStaticDoubleField(JNIEnv*, jclass, jfieldID); void SetObjectField(JNIEnv*, jobject, jfieldID, jobject); void SetBooleanField(JNIEnv*, jobject, jfieldID, jboolean); void SetByteField(JNIEnv*, jobject, jfieldID, jbyte); void SetCharField(JNIEnv*, jobject, jfieldID, jchar); void SetShortField(JNIEnv*, jobject, jfieldID, jshort); void SetIntField(JNIEnv*, jobject, jfieldID, jint); void SetLongField(JNIEnv*, jobject, jfieldID, jlong); void SetFloatField(JNIEnv*, jobject, jfieldID, jfloat); void SetDoubleField(JNIEnv*, jobject, jfieldID, jdouble); // 设置静态字段值 void SetStaticObjectField(JNIEnv*, jclass, jfieldID, jobject); void SetStaticBooleanField(JNIEnv*, jclass, jfieldID, jboolean); void SetStaticByteField(JNIEnv*, jclass, jfieldID, jbyte); void SetStaticCharField(JNIEnv*, jclass, jfieldID, jchar); void SetStaticShortField(JNIEnv*, jclass, jfieldID, jshort); void SetStaticIntField(JNIEnv*, jclass, jfieldID, jint); void SetStaticLongField(JNIEnv*, jclass, jfieldID, jlong); void SetStaticFloatField(JNIEnv*, jclass, jfieldID, jfloat); void SetStaticDoubleField(JNIEnv*, jclass, jfieldID, jdouble);
GetMethodID / CallXxxMethod
GetStaticMethodID / CallStaticXxxMethod
/* * @param env: JNI 接口指针。 * @param clazz:一个 Java 类。 * @param name:方法名称,以 \0 结尾的 UTF-8 字符串。 * @param sig:方法签名,以 \0 结尾的 UTF-8 字符串。 * @return 返回方法 ID,如果操作失败返回 NULL。 */ jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig); // 获取静态方法 jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig); /* * 调用实例方法 * * @param env: JNI 接口指针。 * @param jobject: 一个 Java 对象。 * @param methodID:java 函数的 methodID, 必须通过调用 GetMethodID() 来获得。 * @param ...:java 函数的参数。 * @param args:java 函数的参数数组。 * @param args:java 函数参数的 va_list。 * @return 返回 Java 对象,无法构造该对象则返回 NULL。 */ jobject CallObjectMethod(JNIEnv*, jobject, jmethodID, ...); jobject CallObjectMethodV(JNIEnv*, jobject, jmethodID, va_list); jobject CallObjectMethodA(JNIEnv*, jobject, jmethodID, const jvalue*); jboolean CallBooleanMethod(JNIEnv*, jobject, jmethodID, ...); jboolean CallBooleanMethodV
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。