JNI之函数介绍二

NDK  2023年7月23日 am8:08发布1年前 (2023)更新 城堡大人
91 0 0

前言

今天介绍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头文件完整内容

 历史上的今天

  1. 2021: 博尔赫斯:我用什么才能留住你(0条评论)
  2. 2019: 泰戈尔:你一定要走吗?(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

[摘]final、finally与finalize的区别

final在Java中final可以用来修饰类,方法和变量(成员变量和局部变量)。修饰类当用final修饰类时,表示该类不能被其他类继承。同时,final修饰的类中的方法和都会隐式的定义为final 方法。修饰方法final修饰的方法表示不能被重写。注意:若父类中final方法的访问...

adb shell input的使用

查看当前机器支持adb shell input 的命令如下可以查询C:\Users\Administrator>adb shellroot@android:/ # inputinputusage: input ...input text <string>input k...

git config时fatal not in a git directory

前言最近通过git config修改邮箱和密码是出行如下异常提示:fatal: not in a git directory记录一下,方便自己查阅正文之前使用git config时也没有出行这样的问题,但最近在客户的虚拟机中折腾就出现了。常用命令git config --listg...

Android动画之ScaleAnimation使用

Android动画View Animation 视图动画(Tween Animation 补间动画),只能用来设置View的动画Drawable Animation 帧动画(Frame动画),一帧帧地显示资源文件中的DrawableProperty Animation 属性动画,在andr...

[转]毕业5年决定人的一生

大家千万不要错过这篇文章,毕业三年多了,能看到这篇文章也是一种幸运,真的受益匪浅,对我有很大启迪,这篇文章将会改变我的一生,真的太好了,希望与有缘人分享,也希望对有缘人有所帮助!看完之后有种“相见恨晚”的感觉,特别激动,希望大家好好的珍藏这篇文章,相信多年以后,再来看这篇文章,一定有不同的感...

Android设置语言偏好后应用没有获取对设置的语言

前言之前朋友记录过,如两篇参考文章,今天特意看了一下,竟然有点重复,懒得删了。今天又遇到一种情况,获取不到系统配置的语言选项。记录于此,方便自己查阅。正文根据之前两篇文章,我们知道获取Configuration有如下方式隐藏内容!付费阅读后才能查看!¥1 ¥3多个隐藏块只需支付一次付费阅...