目录
今天介绍JNI中全局及局部引用,对象操作,访问对象的域等函数的操作。
正文
主要涉及全局及局部引用,对象操作,访问对象的域等常用函数。
NewGlobalRef
jobject NewGlobalRef(JNIEnv *env, jobject obj);
建obj 参数所引用对象的新全局引用。obj 参数既可以是全局引用,也可以是局部引用。
全局引用通过调用 DeleteGlobalRef() 来显式撤消。
obj为全局或局部引用。
返回全局引用。如果系统内存不足则返回 NULL。
DeleteGlobalRef
void DeleteGlobalRef(JNIEnv *env, jobject globalRef);
globalRef是全局引用。
DeleteLocalRef
void DeleteLocalRef(JNIEnv *env, jobject localRef);
删除localRef 所指向的局部引用。
AllocObject
jobject AllocObject(JNIEnv *env, jclass clazz);
分配新 Java 对象而不调用该对象的任何构造函数。返回该对象的引用。
clazz 参数务必不要引用数组类。
clazz是Java类对象。
静态方法中的第二个参数就是jclass
返回为Java对象。如果无法构造该对象,则返回 NULL。
当然,也可能出现抛出如下异常:
-
InstantiationException:如果该类为一个接口或抽象类。
-
OutOfMemoryError:如果系统内存不足。
GetObjectClass
jclass GetObjectClass(JNIEnv *env, jobject obj);
返回对象的类。
obj为Java 对象(不能为 NULL)。
非静态方法中的第二个参数就是jobject
一般在非静态类中通过jobject获取jclass。
IsInstanceOf
jboolean IsInstanceOf(JNIEnv *env, jobject obj,jclass clazz)
测试对象obj是否为某个类clazz的实例。
如果可将 obj 强制转换为 clazz, 则返回 JNI_TRUE。 否则返回 JNI_FALSE。
NULL对象可强制转换为任何类。
IsSameObject
jboolean IsSameObject(JNIEnv *env, jobject ref1,jobject ref2)
测试两个引用是否引用同一 Java 对象。
如果 ref1 和 ref2 引用同一 Java 对象或均为 NULL, 则返回 JNI_TRUE。 否则返回 JNI_FALSE。
GetFieldID
jfieldID GetFieldID(JNIEnv *env, jclass clazz,const char *name, const char *sig); jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz,const char *name, const char *sig);
返回类的实例(非静态)域的域 ID。
-
env JNIEnv指针
-
clazz 类对象
-
name java中变量名(域名)
-
sig java变量类型签名(域签名)
如果成功,返回域 ID。如果操作失败,则返回 NULL。
当然,这个也存在抛出异常,有如下情况。
-
NoSuchFieldError:如果找不到指定的域。
-
ExceptionInInitializerError:如果由于异常而导致类初始化程序失败。
-
OutOfMemoryError:如果系统内存不足。
举个例子:
# java public int mIntValue = -0Xff; public static boolean mBooleanValue = true; # C++ # 非静态 jfieldID intFieldID = env->GetFieldID(clazz, "mIntValue", "I"); # 静态 jfieldID booleanFieldID = env->GetStaticFieldID(clazz, "mBooleanValue", "Z");
对于静态和非静态的get方法,JNI中有不一样的定义。以此类推,其他的get或set也是这样。
Get<type>Field
#非静态 NativeType Get<type>Field(JNIEnv *env, jobject obj,jfieldID fieldID) #静态 NativeType GetStatic<type>Field(JNIEnv *env, jclass clazz,jfieldID fieldID)
注意咯,第二个参数不一样哈!!
Get<type>Field和 GetStatic<type>Field是用于获取jfieldID中的值。其中的type表示数据类型比如int,boolean等基本数据类型。
# 非静态[部分] GetObjectField() jobject GetBooleanField() jboolean GetByteField() jbyte GetIntField() jint GetFloatField() jfloat # 静态[部分] GetStaticObjectField() jobject GetStaticBooleanField() jboolean GetStaticByteField() jbyte GetStaticIntField() jint GetStaticFloatField() jfloat
举个例子
# C++ # 非静态 int intValue = env->GetIntField(object, intFieldID); # 静态 int booleanValue = env->GetStaticBooleanField(clazz, booleanFieldID);
Set<type>Field
#非静态 NativeType Set<type>Field(JNIEnv *env, jobject obj,jfieldID fieldID,NativeType value) #静态 NativeType SetStatic<type>Field(JNIEnv *env, jclass clazz,jfieldID fieldID,NativeType value)
跟上面Get<type>Field和GetStatic<type>Field一样,只不过这个是改变值而已。
具体的就不细说,来个例子哈。
#C++ # 非静态 env->SetIntField(object, intFieldID, 99); # 静态 env->SetStaticBooleanField(clazz, booleanFieldID, false);
GetMethodID
jmethodID GetMethodID(JNIEnv *env, jclass clazz,const char *name, const char *sig) jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz,const char *name, const char *sig)
也是两个方法,一个静态一个非静态。
返回类或接口实例(非静态) 方法的方法 ID。 方法可在某个 clazz 的超类中定义,也可从 clazz 继承。该方法由其名称和签名决定。
GetMethodID() 可使未初始化的类初始化。
如果成功,返回方法 ID,否则为 NULL。
这里也设计四个参数:
-
env JNIEnv指针
-
clazz 类对象
-
name java中方法名
-
sig java方法名类型签名
当然,这个也存在抛出异常,有如下情况。
-
NoSuchMethodError:如果找不到指定方法。
-
ExceptionInInitializerError:如果由于异常而导致类初始化程序失败。
-
OutOfMemoryError:如果系统内存不足。
举个例子玩玩
# Hello.java中 # 非静态 public int add(int x, int y) { return x + y; } # 非静态 public int sub(int x, int y) { return x - y; } # 静态 public static int multiply(int x, int y) { return x * y; }
# C++ # 非静态方法 jmethodID addMethodID = env->GetMethodID(clazz, "add", "(II)I"); jmethodID subMethodID = env->GetMethodID(clazz, "sub", "(II)I"); # 静态方法 jmethodID multiplyMethodId = env->GetStaticMethodID(clazz, "multiply", "(II)I");
Call<type>Method
NativeType Call<type>Method(JNIEnv *env, jobject obj,jmethodID methodID, ...); NativeType CallStatic<type>Method(JNIEnv *env, jclass clazz,jmethodID methodID, ...);
参数可变,至少3个,后面跟多少跟调用的java方法有关系。
注意咯,第二个参数不一样哈!!
用例子解释吧。[subMethodID等上面例子中获取的]
# C++ # 非静态 jint count = env->CallIntMethod(object, subMethodID, x, y); jint count = env->CallIntMethod(object, addMethodID, x, y); # 静态 jint count = env->CallStaticIntMethod(clazz, multiplyMethodId, x, y);
参考文章
-
《]》
-
《》