美文网首页
JNI基础(7): JNI访问和修改Java类

JNI基础(7): JNI访问和修改Java类

作者: MemetGhini | 来源:发表于2022-01-12 23:29 被阅读0次
    7.1 java中的基本类型和引用类型的签名规则
    • jni中 java类的签名为: L + 包名 + 类名,再将原来的.改为/分隔符即可。
      例如:java中的java.lang.String的签名为Ljava/lang/String;

    • java中的基本类型的签名为:

    Field Descriptor Java Language Type
    Z boolean
    B byte
    C char
    S short
    I int
    J long
    F float
    D double
    V void
    Object L用/分割的包名
    • java 中的数组的签名为:左中括号+对象或者基本类型的签名即可;
    Field Descriptor Java Language Type
    object[] [Ljava/lang/Object;
    int[] [I
    float[] [F
    7.2 JNI中访问访问java对象的字段并修改

    JNI中修改任何java对象的字段值一般分为如下三步:

    • 先找到类
    • 找到类的字段id
    • 通过字段id获取或者更新对象的该字段

    如果类实例中还存在别的类的实例 也是按上面的逻辑分析一层层解剖就行

    例如:
    定义一个叫Person的java类和House的java类:

    public class House {
        public int size = 100;
        public String location = "Beijing";
    }
    
    public class Person {
    
        protected String name;
        protected int age;
        protected House house;
        public static int num = 0;
    
        public Person(String name)
        {
            this.name = name;
            this.house = new House();
        }
        public String getName() {
            return name;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public int getAge() {
            return age;
        }
        public static int getNum() {
            return num;
        }
    }
    

    在默认工程的MainActivity添加两个JNI方法声明第一个为成员访问,第二个静态方法。他们在JNI层的生成的代码是不一样的。在成员实例方法jni方法中的前两个参数 : JNIEnv env, jobject thiz。thiz代表着所在java类的实例。例如本例中是MainActivity的java实例。取决于这个方法生命在哪个类中。

    public native void accessField(Person person);
    

    在static 的 jni方法中的前两个参数 : JNIEnv *env, jclass clazz。clazz代表着所在java类。例如本例中是MainActivity的java类。取决于这个方法生命在哪个类中。

    public static native void accessStaticField(Person person);
    

    接下来在jni中访问Person类的成员变量:

    extern "C"
    JNIEXPORT void JNICALL
    Java_com_memetghini_javaobject_MainActivity_accessField(JNIEnv *env, jobject thiz, jobject person) {
        //成员变量
        //首先找到类,参数是jni对象
        jclass cls = env->GetObjectClass(person);
        //再找到成员变量字段id。第一个参数是上面找到的类,第二个参数是字段名,第三个参数为字段签名
        jfieldID fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
        //为该成员变量设值,第一个参数为jni对象,第二个参数为要设值的字段id,第三个参数为具体的值
        jstring str = env->NewStringUTF("Kadi");
        env->SetObjectField(person, fid, str);
    
        //成员对象
        //上面已经找到了类,所以先直接找到字段id
        jfieldID house_fid = env->GetFieldID(cls, "house", "Lcom/memetghini/javaobject/House;");
        //再找jni对象,再从对象中获取字段值或者更改内容,接下来的跟上面相似
        jobject house_obj = env->GetObjectField(person, house_fid);
        jclass house_cls = env->GetObjectClass(house_obj);
        jfieldID size_fid = env->GetFieldID(house_cls, "size", "I");
        env->SetIntField(house_obj, size_fid, 1000000);
    }
    
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_memetghini_javaobject_MainActivity_accessStaticField(JNIEnv *env, jclass clazz, jobject person) {
        //静态变量的读取也是一样的先通过GetStaticFieldID获取静态变量的字段id
        jfieldID num_fid = env->GetStaticFieldID(clazz, "num", "I");
        //在用静态变量的字段id获取具体的值。第一个变量为类类型,第二个为静态变量字段id
        int num = env->GetStaticIntField(clazz, num_fid);
        LOGI("jni num main = %d", num);
        //更改静态变量的值。第一个参数为类类型,第二个为静态变量字段id,第三个为具体的值
        env->SetStaticIntField(clazz, num_fid, 777);
    }
    
    

    相关文章

      网友评论

          本文标题:JNI基础(7): JNI访问和修改Java类

          本文链接:https://www.haomeiwen.com/subject/fpcpcrtx.html