您的位置:首页 > 其它

NDK开发之访问域

2015-09-05 12:14 169 查看
Java有两类域,实例域和静态域。类的每个实例都有自己的实例域副本,而一个类的所有实例共享一个静态域(Java SE基础)。

JNI提供了相应的函数来访问这两类域,总体步骤是这样的:

1.通过对象引用获得类

2.通过类获得域ID

3.通过域ID获取域

下面我们按步骤一步一步来:

我们的Java类中有两个域,一个静态域,一个实例域:

private static String staticFiled = "a static Filed465";
private String instanceFiled = "a instance Filed123";


访问该域的三个步骤:

1通过对象引用获得类

jclass clazz;
//定义域ID
jfieldID instanceFieldId;
jfieldID staticFieldId;
//定义域
jstring instanceFieldStr;
jstring staticFieldStr;
//通过对象引用获得类
clazz = (*env)->GetObjectClass(env, thiz);


2通过类获得域ID

//通过类获得域ID
instanceFieldId = (*env)->GetFieldID(env,clazz,"instanceFiled","Ljava/lang/String;");
staticFieldId = (*env)->GetStaticFieldID(env,clazz,"staticFiled","Ljava/lang/String;");


这里两个函数的最后一个参数是Java中表示域类型的域描述符,
"Ljava/lang/String;"
表明域类型是String。

一般情况下,为了提高应用程序的性能,我们可以缓存域ID,一般总是缓存使用最频繁的域ID

3.通过域ID获取域

//通过域ID获得域
instanceFieldStr = (*env)->GetObjectField(env,thiz,instanceFieldId);
staticFieldStr = (*env)->GetStaticObjectField(env,clazz,staticFieldId);


为了证明我们已经成功获得域,我们把jstring转为c字符串之后然后打印出来(打印日志请看NDK开发之日志打印):

const jbyte* str1;
const jbyte* str2;
str1 = (*env)->GetStringUTFChars(env,instanceFieldStr,0);
str2 = (*env)->GetStringUTFChars(env,staticFieldStr,0);
LOGI("the string is :%s",str1);
LOGI("the string is :%s",str2);


打印结果:



完整的程序是这样的:

void Java_com_example_jni_MainActivity_updateField(JNIEnv* env, jobject thiz) {
jclass clazz; //定义域ID jfieldID instanceFieldId; jfieldID staticFieldId; //定义域 jstring instanceFieldStr; jstring staticFieldStr; //通过对象引用获得类 clazz = (*env)->GetObjectClass(env, thiz);
//通过类获得域ID instanceFieldId = (*env)->GetFieldID(env,clazz,"instanceFiled","Ljava/lang/String;"); staticFieldId = (*env)->GetStaticFieldID(env,clazz,"staticFiled","Ljava/lang/String;");
//通过域ID获得域
instanceFieldStr = (*env)->GetObjectField(env,thiz,instanceFieldId);
staticFieldStr = (*env)->GetStaticObjectField(env,clazz,staticFieldId);
//jstring转为C字符串然后打印出来
const jbyte* str1;
const jbyte* str2;
str1 = (*env)->GetStringUTFChars(env,instanceFieldStr,0);
str2 = (*env)->GetStringUTFChars(env,staticFieldStr,0);
LOGI("the string is :%s",str1);
LOGI("the string is :%s",str2);
}


总结

大家都看到了,获得单个域需要三个步骤,这真是太麻烦了,经常这样搞会影响程序的性能,因此建议如果在原生方法中需要 使用域,这些域最好作为参数传递给原生方法,而不要让原生代码回到Java中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: