JNI之函数介绍二

NDK  2023年7月23日 am8:08发布1年前 (2023)更新 91es.com站长
73 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、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

Application多次初始化

前言如果一个apk中在设置多进程,也就是在AndroidManifest.xml中,通过android:process属性配置。<activity   android:name=".OneActivity"   android:exported="true"   androi...

Kotlin数组简介

前言简单记录一下Kotlin中数组的使用。正文数组是指一组数据的集合,数组中的每个数据被称作元素。在数组中可以存放任意类型的元素,但同一个数组中存放的元素类型必须一致。数组可分为一维数组和多维数组。一维数组在Kotlin中,数组使用Array表示,其中数值类型、布尔类型、字符类型、字符...

Android消息机制之三Handler分析

接着《Android消息机制之一简介(1)》和《Android消息机制之二简介(2)》,我们现在来单独看看Handler源码。设计代码的路径:base\core\java\android\os\Handler.javaHandler的简单使用在项目中,Handler的声明和初始化一般...

Android数据库查询记录

前言记录一下数据库查询,模糊查询等Java方法,方便自己查阅。正文查询Android多媒体下面是查询audio文件隐藏内容!付费阅读后才能查看!¥2 ¥3多个隐藏块只需支付一次付费阅读匹配查询数据查询可以分为精准匹配查询,也可以模糊匹配查询。like 模糊查询隐藏内容!付费阅读后...

WordPress页面中阻止插入额外换行

众所周知WordPress会对编辑器里的内容再格式化一遍,比如自动分段。但有些时候这些添加的格式反而也会让人很头疼。最近遇到WordPress在input,select,pre前会插入额外的换行即<br>,从而破坏页面样式的问题。方法一:去除所有页面的额外换行符在对应主题f...

ATC平台编译命令记录

前言主要记录一下ATC项目中用的编译命令。方便自己查阅。主要是个人用,每个平台可能不一样。不推荐看哈正文在Android源码目录下隐藏内容!付费阅读后才能查看!¥2 ¥3多个隐藏块只需支付一次付费阅读参考文章1.《ATC 文档》