导航号,我的单页导航
文章目录

前言

今天介绍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。

当然,也可能出现抛出如下异常:

  1. InstantiationException:如果该类为一个接口或抽象类。

  2. 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。

  1. env JNIEnv指针

  2. clazz 类对象

  3. name java中变量名(域名)

  4. sig java变量类型签名(域签名)

如果成功,返回域 ID。如果操作失败,则返回 NULL。

当然,这个也存在抛出异常,有如下情况。

  1. NoSuchFieldError:如果找不到指定的域。

  2. ExceptionInInitializerError:如果由于异常而导致类初始化程序失败。

  3. 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。

这里也设计四个参数:

  1. env JNIEnv指针

  2. clazz 类对象

  3. name java中方法名

  4. sig java方法名类型签名

当然,这个也存在抛出异常,有如下情况。

  1. NoSuchMethodError:如果找不到指定方法。

  2. ExceptionInInitializerError:如果由于异常而导致类初始化程序失败。

  3. 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, ...);

用于从本地方法调用Java 实例方法 。也是分静态和非静态的。type也就是基本数据类型,这不再重复解释了。

参数可变,至少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);

参考文章

  1. JNI完全手册]》

  2. NDK中jni.h头文件完整内容

© 版权声明
导航号,我的单页导航

暂无评论

暂无评论...