Android JNI开发系列(十)JNI访问 Java 实例变量和静态变量


声明:本文转载自https://my.oschina.net/u/1433837/blog/2246885,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

JNI访问 Java 实例变量和静态变量

Java 中的实例变量和静态变量,在本地代码中如何来访问和修改。静态变量也称为类变量(属性),在所有实例对象中共享同一份数据,可以直接通过类名.变量名来访问。实例变量也称为成员变量(属性),每个实例都拥有一份实例变量数据的拷贝,它们之间修改后的数据互不影响。

直接上代码:

JAVA

public class Person {

    //成员变量 
    private String hobby;

    //静态变量
    private static int happiness;

    public String getHobby() {
        return hobby;
    }

    public static int getHappiness() {
        return happiness;
    }

    //Native方法中设置成员变量的值
    public native boolean setHobby();
    
    //Native方法中设置静态变量的值
    public native boolean setHappiness();
}

Native

JNIEXPORT jboolean JNICALL
Java_org_professor_jni_bean_Person_setHobby(JNIEnv *env, jobject instance) {

//1.获取类类型的Class对象
jclass personClass = (*env)->FindClass(env, "org/professor/jni/Person");
if (NULL == personClass) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON", "NOT FIND CLASS");
    return JNI_FALSE;
}
//2.获取属性ID
jfieldID hobbyFiledID = (*env)->GetFieldID(env, personClass, "hobby", "Ljava/long/String");

if (NULL == hobbyFiledID) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON", "NOT FIND Hobby FiledID");
    return JNI_FALSE;
}

//3.实例属性,通过对象获取属性值
jstring hobbyFiledStr = (*env)->GetObjectField(env, instance, hobbyFiledID);
if (NULL != hobbyFiledStr) {
    const char *hobby = (*env)->GetStringUTFChars(env, hobbyFiledStr, NULL);
    if (NULL != hobby) {
        __android_log_print(ANDROID_LOG_ERROR, "PERSON Hobby", hobby);
        (*env)->ReleaseStringChars(env, hobbyFiledStr, hobby);
    }
}
//4.设置属性值
jstring jHobby = (*env)->NewStringUTF(env, "BASKETBALL,RUN");
(*env)->SetObjectField(env, instance, hobbyFiledID, jHobby);
//5.删除局部引用变量
(*env)->DeleteLocalRef(env, personClass);
(*env)->DeleteLocalRef(env, hobbyFiledStr);
(*env)->DeleteLocalRef(env, jHobby);
return JNI_TRUE;
}


JNIEXPORT jboolean JNICALL
Java_org_professor_jni_bean_Person_setHappiness(JNIEnv *env, jobject instance) {

//1.获取类类型的Class对象
jclass personClass = (*env)->FindClass(env, "org/professor/jni/Person");
if (NULL == personClass) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON", "NOT FIND CLASS");
    return JNI_FALSE;
}
//2.获取属性ID

jfieldID happinessFiledID = (*env)->GetStaticFieldID(env, personClass, "happiness", "I");

if (NULL == happinessFiledID) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON", "NOT FIND Happiness FiledID");
    return JNI_FALSE;
}

//3.获取静态属性值
jint happinessValue = (*env)->GetStaticIntField(env, personClass, happinessFiledID);
if (NULL != happinessValue) {
    __android_log_print(ANDROID_LOG_ERROR, "PERSON happinessValue = %d",
                        (const char *) happinessValue);
}

//4.设置静态属性值
(*env)->SetStaticIntField(env, personClass, happinessFiledID, 80);

//5.删除本地局部引用表,基本数据类型不需要
(*env)->DeleteLocalRef(env, personClass);
return JNI_TRUE;
}

小结

  • 由于JNI 函数是直接操作JVM中的数据结构,不受 Java访问修饰符的限制。即,Native代码中调用 JNI函数可以访问 Java 对象中的非 public 属性和方法
  • 访问和修改实例变量操作步聚
    • 调用 GetObjectClass 函数获取实例对象的 Class 引用
    • 调用 GetFieldID 函数获取 Class 引用中某个实例变量的 ID
    • 调用 GetXXXField 函数获取变量的值,需要传入实例变量所属对象和变量 ID
    • 调用 SetXXXField 函数修改变量的值,需要传入实例变量所属对象、变量 ID 和变量的值
  • 访问和修改静态变量操作步聚:
    • 调用 FindClass 函数获取类的 Class 引用
    • 调用 GetStaticFieldID 函数获取 Class 引用中某个静态变量 ID
    • 调用 GetStaticXXXField 函数获取静态变量的值,需要传入变量所属 Class 的引用和变量 ID
    • 调用 SetStaticXXXField 函数设置静态变量的值,需要传入变量所属 Class 的引用、变量 ID和变量的值

本文发表于2018年10月16日 13:00
(c)注:本文转载自https://my.oschina.net/u/1433837/blog/2246885,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1771 讨论 0 喜欢 3

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1