NDK开发之访问域

举报
江南一点雨 发表于 2021/08/16 22:40:28 2021/08/16
【摘要】 Java有两类域,实例域和静态域。类的每个实例都有自己的实例域副本,而一个类的所有实例共享一个静态域(Java SE基础)。 JNI提供了相应的函数来访问这两类域,总体步骤是这样的: 1.通过对象引用获得类 2.通过类获得域ID 3.通过域ID获取域 下面我们按步骤一步一步来: 我们的Java类中有两个域,一个静态域,一个实例域: private...

Java有两类域,实例域和静态域。类的每个实例都有自己的实例域副本,而一个类的所有实例共享一个静态域(Java SE基础)。

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


1.通过对象引用获得类
2.通过类获得域ID
3.通过域ID获取域


下面我们按步骤一步一步来:
我们的Java类中有两个域,一个静态域,一个实例域:

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

访问该域的三个步骤:

1通过对象引用获得类

jclass clazz; //定义域ID jfieldID instanceFieldId; jfieldID staticFieldId; //定义域 jstring instanceFieldStr; jstring staticFieldStr; //通过对象引用获得类 clazz = (*env)->GetObjectClass(env, thiz);
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2通过类获得域ID

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

这里两个函数的最后一个参数是Java中表示域类型的域描述符,"Ljava/lang/String;"表明域类型是String。
一般情况下,为了提高应用程序的性能,我们可以缓存域ID,一般总是缓存使用最频繁的域ID

3.通过域ID获取域

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

为了证明我们已经成功获得域,我们把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);
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

打印结果:

这里写图片描述


完整的程序是这样的:


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);
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

总结

大家都看到了,获得单个域需要三个步骤,这真是太麻烦了,经常这样搞会影响程序的性能,因此建议如果在原生方法中需要 使用域,这些域最好作为参数传递给原生方法,而不要让原生代码回到Java中。


文章来源: wangsong.blog.csdn.net,作者:_江南一点雨,版权归原作者所有,如需转载,请联系作者。

原文链接:wangsong.blog.csdn.net/article/details/48224013

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。