JNI新建对象和访问Java中属性
本章主要写代码测试在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 进行许可。
评论