JNI新建对象和访问Java中属性

xiaoeryu Lv5

本章主要写代码测试在JNI中使用JNIEnv提供的接口,创建Java对象以及访问Java类中的属性(静态属性、非静态属性、数组)

JNI中创建Java对象

  • 使用NewObject()和AllocObject()两种方式创建JAVA对象
extern "C"
JNIEXPORT void JNICALL
Java_com_xiaoeryu_reflectiontest_MainActivity_newObject(JNIEnv *env, jobject thiz) {
    // TODO: implement newObject()
    // 使用函数NewObject来创建JAVA对象
    jclass TestJclass = env->FindClass("com/xiaoeryu/reflectiontest/Test");
    // public Test(String arg)
    jmethodID con_mid = env->GetMethodID(TestJclass, "<init>", "(Ljava/lang/String;)V");
    jstring arg = env->NewStringUTF("I am From jni");
    // jobject NewObject(jclass clazz, jmethodID methodID, ...)
    jobject testobj = env->NewObject(TestJclass, con_mid, arg);
    if (testobj != nullptr){
        __android_log_print(4, "xiaoeryu->jni", "jni->%s", "NewObject success!");
    }

    // AllocObject
    jobject testobj1 = env->AllocObject(TestJclass);
    jstring arg1 = env->NewStringUTF("I am From Jni->AllocObject");
    env->CallNonvirtualVoidMethod(testobj1, TestJclass, con_mid, arg1);
    if (testobj1 != nullptr){
        __android_log_print(4, "xiaoeryu->jni", "jni->%s", "AllocObject success!");
    }
}

JNI获取Java中的构造函数的时候,函数名写

JNI中访问类对象属性

Java中有public和private

在JNI中只分静态属性和非静态属性

Static属性

获取Static属性

  • 获取静态属性接口(有八种基础数据类型+一种引用数据类型)
    jobject GetStaticObjectField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticObjectField(this, clazz, fieldID); }
    jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticBooleanField(this, clazz, fieldID); }
    jbyte GetStaticByteField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticByteField(this, clazz, fieldID); }
    jchar GetStaticCharField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticCharField(this, clazz, fieldID); }
    jshort GetStaticShortField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticShortField(this, clazz, fieldID); }
    jint GetStaticIntField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticIntField(this, clazz, fieldID); }
    jlong GetStaticLongField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticLongField(this, clazz, fieldID); }
    jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticFloatField(this, clazz, fieldID); }
    jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID)
    { return functions->GetStaticDoubleField(this, clazz, fieldID); }
  • 获取静态属性code
extern "C"
JNIEXPORT void JNICALL
Java_com_xiaoeryu_reflectiontest_MainActivity_getStaticField(JNIEnv *env, jobject thiz) {
// public static
    jclass TestJclass = env->FindClass("com/xiaoeryu/reflectiontest/Test");
    // public static String publicStaticField = "i am a public StaticField";
    jfieldID publicStaticField_id = env->GetStaticFieldID(TestJclass, "publicStaticField", "Ljava/lang/String;");
    jstring publicStaticField_obj = static_cast<jstring>(env->GetStaticObjectField(TestJclass, publicStaticField_id));
    const char *publicStaticField_content = env->GetStringUTFChars(publicStaticField_obj, nullptr);

    __android_log_print(4, "xiaoeryu->jni", "publicStaticField_obj_jni->%s", publicStaticField_content);

    // private static String priviteStaticField = "i am a private StaticField";
    jfieldID privateStaticField_id = env->GetStaticFieldID(TestJclass, "priviteStaticField", "Ljava/lang/String;");
    jstring privateStaticField_obj = static_cast<jstring>(env->GetStaticObjectField(TestJclass, privateStaticField_id));
    const char *privateStaticField_content = env->GetStringUTFChars(privateStaticField_obj, nullptr);

    __android_log_print(4, "xiaoeryu->jni", "privateStaticField_obj_jni->%s", privateStaticField_content);

    // public static int publicStaticField_int = 100;
    jfieldID publicStaticField_int_id = env->GetStaticFieldID(TestJclass, "publicStaticField_int", "I");
    jint publicStaticField_int_value = env->GetStaticIntField(TestJclass, publicStaticField_int_id);

    __android_log_print(4, "xiaoeryu->jni", "publicStaticField_int_value_jni->%d", publicStaticField_int_value);
}

在native中访问java类中的私有静态属性需不需要修改权限都可以直接获取,在获取不同类型数据的时候换不同的接口就行例如GetStaticFieldID/GetStaticIntField

设置Static属性

  • 设置静态类属性接口
    void SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject value)
    { functions->SetStaticObjectField(this, clazz, fieldID, value); }
    void SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value)
    { functions->SetStaticBooleanField(this, clazz, fieldID, value); }
    void SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte value)
    { functions->SetStaticByteField(this, clazz, fieldID, value); }
    void SetStaticCharField(jclass clazz, jfieldID fieldID, jchar value)
    { functions->SetStaticCharField(this, clazz, fieldID, value); }
    void SetStaticShortField(jclass clazz, jfieldID fieldID, jshort value)
    { functions->SetStaticShortField(this, clazz, fieldID, value); }
    void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value)
    { functions->SetStaticIntField(this, clazz, fieldID, value); }
    void SetStaticLongField(jclass clazz, jfieldID fieldID, jlong value)
    { functions->SetStaticLongField(this, clazz, fieldID, value); }
    void SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat value)
    { functions->SetStaticFloatField(this, clazz, fieldID, value); }
    void SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble value)
    { functions->SetStaticDoubleField(this, clazz, fieldID, value); }

设置静态属性code

    jclass TestJclass = env->FindClass("com/xiaoeryu/reflectiontest/Test");
    jfieldID publicStaticField_id = env->GetStaticFieldID(TestJclass, "publicStaticField", "Ljava/lang/String;");

    jstring setjstring = env->NewStringUTF("modified by jni");
    env->SetStaticObjectField(TestJclass, publicStaticField_id, setjstring);
    jstring publicStaticField_obj = static_cast<jstring>(env->GetStaticObjectField(TestJclass, publicStaticField_id));
...
    // public static int publicStaticField_int = 100;
    jfieldID publicStaticField_int_id = env->GetStaticFieldID(TestJclass, "publicStaticField_int", "I");

    // void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value)
    env->SetStaticIntField(TestJclass, publicStaticField_int_id, 20);

    jint publicStaticField_int_value = env->GetStaticIntField(TestJclass, publicStaticField_int_id);

    __android_log_print(4, "xiaoeryu->jni", "publicStaticField_int_value_jni->%d", publicStaticField_int_value);

非Static属性

这里新版编译器有可能报错,但是不影响编译执行

获取&设置非静态私有属性

  • 设置非静态私有类属性接口
    void SetObjectField(jobject obj, jfieldID fieldID, jobject value)
    { functions->SetObjectField(this, obj, fieldID, value); }
    void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value)
    { functions->SetBooleanField(this, obj, fieldID, value); }
    void SetByteField(jobject obj, jfieldID fieldID, jbyte value)
    { functions->SetByteField(this, obj, fieldID, value); }
    void SetCharField(jobject obj, jfieldID fieldID, jchar value)
    { functions->SetCharField(this, obj, fieldID, value); }
    void SetShortField(jobject obj, jfieldID fieldID, jshort value)
    { functions->SetShortField(this, obj, fieldID, value); }
    void SetIntField(jobject obj, jfieldID fieldID, jint value)
    { functions->SetIntField(this, obj, fieldID, value); }
    void SetLongField(jobject obj, jfieldID fieldID, jlong value)
    { functions->SetLongField(this, obj, fieldID, value); }
    void SetFloatField(jobject obj, jfieldID fieldID, jfloat value)
    { functions->SetFloatField(this, obj, fieldID, value); }
    void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value)
    { functions->SetDoubleField(this, obj, fieldID, value); }
  • 设置非静态私有属性和数组类型
extern "C"
JNIEXPORT void JNICALL
Java_com_xiaoeryu_reflectiontest_MainActivity_getNonStaticField(JNIEnv *env, jobject thiz, jobject testobj) {
    // private String privateField = "i am a private Field";
    jclass TestJclass = env->FindClass("com/xiaoeryu/reflectiontest/Test");
    jfieldID privateField_fid = env->GetFieldID(TestJclass, "privateField", "Ljava/lang/String;");
    //    jobject GetObjectField(jobject obj, jfieldID fieldID)
    jstring privateField_obj = static_cast<jstring>(env->GetObjectField(testobj, privateField_fid));

//    const char *priviteField_content = env->GetStringUTFChars(privateField_obj, nullptr);
//    __android_log_print(4, "xiaoeryu->jni", "privateField_obj_jni->%s", priviteField_content);

    // 修改private String
    jstring newString = env->NewStringUTF("Modified by jni");
    env->SetObjectField(testobj, privateField_fid, newString);

    privateField_obj = static_cast<jstring>(env->GetObjectField(testobj, privateField_fid));

    const char *priviteField_content = env->GetStringUTFChars(privateField_obj, nullptr);
    __android_log_print(4, "xiaoeryu->jni", "privateField_obj_jni->%s", priviteField_content);

    // GetIntField
    // private int privateField_int = 100;
    jfieldID privateField_int_fid = env->GetFieldID(TestJclass, "privateField_int", "I");
    jint privateField_int_value = env->GetIntField(testobj, privateField_int_fid);

    __android_log_print(4, "xiaoeryu->jni", "prinvateField_int_value_jni->%d", privateField_int_value);

    // SetIntField
    env->SetIntField(testobj, privateField_int_fid, 200);
    jint privateField_int_setValue = env->GetIntField(testobj, privateField_int_fid);

    __android_log_print(4, "xiaoeryu->jni", "privateField_int_vale_jni->%d", privateField_int_setValue);

    // 数组
    // public int[] intarray = null;
    jfieldID intarray_fid = env->GetFieldID(TestJclass, "intarray", "[I");
    jintArray intarray_obj = static_cast<jintArray>(env->GetObjectField(testobj, intarray_fid));

    int arrayLenght = env->GetArrayLength(intarray_obj);

    __android_log_print(4, "xiaoeryu->jni", "arrayLenght_jni->%d", arrayLenght);

    int* array = env->GetIntArrayElements(intarray_obj, nullptr);
    for (int i = 0; i < arrayLenght; ++i) {
        __android_log_print(4, "xiaoeryu->jni", "array[%d]->%d", i, array[i]);
    }
    // setArray
    jint jni_array[arrayLenght];
    for (int j = 0; j < arrayLenght; ++j) {
        jni_array[j] = arrayLenght - j;
    }
    const jint* ptr = jni_array;
    //     void SetIntArrayRegion(jintArray array, jsize start, jsize len,
    //        const jint* buf)
    env->SetIntArrayRegion(intarray_obj, 0, arrayLenght, ptr);

    int* array_set = env->GetIntArrayElements(intarray_obj, nullptr);
    for (int i = 0; i < arrayLenght; ++i) {
        __android_log_print(4, "xiaoeryu->jni", "array_set[%d]->%d", i, array_set[i]);
    }
}

访问数组的操作方法

代码地址

  • 标题: JNI新建对象和访问Java中属性
  • 作者: xiaoeryu
  • 创建于 : 2023-10-13 23:27:03
  • 更新于 : 2023-10-14 11:14:18
  • 链接: https://github.com/xiaoeryu/2023/10/13/JNI新建对象和访问Java中属性/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论