美文网首页
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