JNI之访问方法和域

NDK开发2023年7月20日 am8:09发布1年前 (2023)更新 3XCN.COM站长
0 0 0
广告也精彩
目录

前言

JNI允许本地方法访问Java对象的域和调用方法。今天就介绍一下放问java方法和对象的域。

记录一下,方便自己查阅。

正文

JNI访问对象域和方法,主要涉及如下几步骤:

  1. 获取到对象域的jfieldID或jmethodID

  2. 通过jfieldID获取对象域的值或者通过jmethodID调用对应的方法。

  3. 对于对象域,还可以通过jfieldID改变值。

下面单独介绍使用。

访问方法

在介绍前,主要注意带有static的方法跟没有static方法的是有区别的。

# 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;
}
第一步

静态和非静态jmethodID的获取方法存在不一,JNI中有区分的。

非静态方法
jmethodID addMethodID = env->GetMethodID(clazz, "add", "(II)I");
jmethodID subMethodID = env->GetMethodID(clazz, "sub", "(II)I");
静态方法
jmethodID multiplyMethodId = env->GetStaticMethodID(clazz, "multiply", "(II)I");

PS: GetxxxMethodID()中是否有static取决于方法中是否有static声明。

看完到上面,你或许跟我一样的想法,static方法是属于类,也属于对象的,那如果我不用JNI定义的static方法获取jmethodID呢?

我尝试了一下,编译是OK的,但运行是异常了。

JNI DETECTED ERROR IN APPLICATION: JNI CallIntMethodV called with pending exception java.lang.NoSuchMethodError: no non-static method "Lcom/biumall/dynamic/one/Hello;.multiply(II)I"

异常中也告诉我们 no non-static method "Lcom/biumall/dynamic/one/Hello;.multiply(II)I"(multiply是静态类),意思就是需要使用静态的方法访问他。

第二步

JNI的函数中可以通过jmethodID进行调用Java的方法。

非静态方法
if(NULL != addMethodID){
    count = env->CallIntMethod(object, addMethodID, x, y);
}
if(NULL != subMethodID){
    count = env->CallIntMethod(object, subMethodID, x, y);
}

CallIntMethod()表示调用非静态的返回值为int的addMethodID或subMethodID方法。

jni.h中还有其他返回类型的方法。

jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
静态方法
if(NULL == multiplyMethodId){
    count = env->CallStaticIntMethod(clazz, multiplyMethodId, x, y);
}

CallStaticIntMethod()表示调用非静态的返回值为int的multiplyMethodId方法。

需要注意的,因为是static方法,所以第二个参数传入的类引用!(重点)

jni.h中还有其他返回类型的方法。

jobject     (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);
jboolean    (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);
jbyte       (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);
jchar       (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);
jshort      (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);
jint        (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);
jfloat      (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...);
jdouble     (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...);
void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);

如果这里不也不使用CallStaticIntMethod(),而是用CallIntMethod()也是会异常的,如下

JNI DETECTED ERROR IN APPLICATION: calling static method int com.biumall.dynamic.one.Hello.multiply(int, int) with CallIntMethodV

访问域

域也分为静态域和非静态的域。

如果乱使用也是会有异常的,显示使用GetFieldID()去获取static的域出现的异常。

JNI DETECTED ERROR IN APPLICATION: JNI GetStringUTFChars called with pending exception java.lang.NoSuchFieldError: no "Z" field "mBooleanValue" in class "Lcom/biumall/dynamic/one/Hello;" or its superclasses

由于域跟访问方法差不多,这就简单的介绍一下。

public int mIntValue = -0Xff;
public static boolean mBooleanValue = true;
非静态
jfieldID intFieldID = env->GetFieldID(clazz, "mIntValue", "I");

if(NULL != intFieldID){
    //获取对象域中的值
    int intValue = env->GetIntField(object, intFieldID);
    //修改对象域中的值
    env->SetIntField(object, intFieldID, 99);
}
静态
jfieldID booleanFieldID = env->GetStaticFieldID(clazz, "mBooleanValue", "Z");
if(NULL !=  booleanFieldID){
    //获取对象域中的值
    int booleanValue = env->GetStaticBooleanField(clazz, booleanFieldID);
    //修改对象域中的值
    env->SetStaticBooleanField(clazz, booleanFieldID, false);
}

上面只涉及int和boolean类,其他的类型jni.h中也有定义哈。

其实只要理解了一个,其他的都很容易的。无非有static和无static的区别。

参考文章

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

 历史上的今天

版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站文章: 部分来源于网络,仅供站长学习和参考,若侵权请留言
广告也精彩

相关文章

广告也精彩

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

暂无评论...

网站升级中

公告

近期网站升级中,可能存在一些bug。欢迎反馈 https://www.91es.com/we.html

本站域名

本站域名 : 91es.com3xcn.com。本站邮箱 : 站长邮箱 i@oorr.cn,通知邮箱we@oorr.cn ,如有更新,请看公告 。