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中。


版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。

NDK开发之访问域的更多相关文章

  1. NDK开发之获得域和方法描述符

    在NDK开发之调用方法和NDK开发之访问域两篇博客中,我们在获得域ID和方法ID时都需要一个叫做描述符的参数,那么在实际开发中我们怎么知道我们要调用的域或者方法的描述符呢? 一个简单的方法就是使用Ja ...

  2. NDK开发之调用方法

    与NDK开发之访问域中介绍的一样,Java中的方法也是分为两类:实例方法和静态方法.JNI提供了访问两类方法的函数,下面我们一起来看看怎么在C中访问Java中的方法. 我们的MainActivity中 ...

  3. Vue开发环境跨域访问

    Vue开发环境跨域访问其他服务器或者本机其他端口,需要配置项目中config/index.js文件,修改如下 module.exports = { dev: { // Paths assetsSubD ...

  4. NDK开发-零散知识点整理

    JavaVM 标准Java平台下,每一个Process可以产生很多JavaVM对象,但在Android平台上,每一个Process只能产生一个Dalvik VM对象,也就是说在Android进程中是通 ...

  5. NDK开发_笔记0

    自谷歌搜索退出中国以来,谷歌对全球第二大市场中国的态度一直保持冷淡.可是北京时间12月8日,谷歌2016开发者大会在北京召开,同时专门针对中国的谷歌开发者网站已经上线:https://develope ...

  6. Android NDK开发Hello Word!

    在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...

  7. Android NDK开发初识

    神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...

  8. Android之NDK开发(转)

    Android之NDK开发 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C++开发.众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第 ...

  9. C#开发中Windows域认证登录2(扩展吉日嘎拉GPM系统)

    原文地址:http://www.cuiwenyuan.com/shanghai/post/Windows-AD-Logon-Intergrated-into-Jirigala-GPM-DotNet-B ...

随机推荐

  1. PYTHON之DEF

    def sayHello(): print('Hello World!') while True: s = input('Enter something : ') if s == 'quit': br ...

  2. 虚拟机安装了ubuntu,忘记密码修复

    在虚拟机中按照以下步骤重新为用户设定新密码. 重启Ubuntu,随即长按shift进入grub菜单: 选择recovery mode,回车确认: 在Recovery Menu中,选择“Root Dro ...

  3. iframe的安全问题

    今天尝试在iframe中嵌入外部网站, 碰到了一些小问题. 如何让自己的网站不被其他网站的iframe引用? 我测试的时候发现我把iframe的src指定到github不起作用. 原来是它把X-Fra ...

  4. 【HDOJ】1890 Robotic Sort

    伸展树伤不起啊,很容易wa,很容易T,很容易M. /* 1890 */ #include <iostream> #include <string> #include <m ...

  5. C++ Primer 随笔 Chapter 4 数组和指针

    1.数组:数组是由类型名.标识符和维数组成的符合数据类型,类型名规定了存放在数组中的元素类型,维数规定数组中包含元素的个数而标识符就是数组的名称.例如: int  arr[10]; 其中 int 是类 ...

  6. bzoj2705

    一个常用的结论(方法) 只要知道gcd(i,n)=L 的i的个数s,我们就能很轻易得出答案 gcd(i,n)=L gcd(i/L,n/L)=1 不难得到这样的s=与n/L互质的个数=phi(n/L) ...

  7. Codevs_1048_石子归并_(动态规划)

    描述 http://codevs.cn/problem/1048/  1048 石子归并 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold       题目描述 Des ...

  8. 使用SQL Server 2014内存数据库时需要注意的地方

    作者 王枫发布于2014年7月4日 本文从产品设计和架构角度分享了Microsoft内存数据库方面的使用经验,希望你在阅读本文之后能够了解这些新的对象.概念,从而更好地设计你的架构. 内存数据库,指的 ...

  9. Entity Framework 学习初级篇1--EF基本概况

    转自:http://www.cnblogs.com/Tally/archive/2012/09/14/2685011.html 最近在学习研究微软的EF,通过这时间的学习研究,感觉这个EF目前来说还不 ...

  10. java基础(十六)集合(三)

    这里有我之前上课总结的一些知识点以及代码大部分是老师讲的笔记 个人认为是非常好的,,也是比较经典的内容,真诚的希望这些对于那些想学习的人有所帮助! 由于代码是分模块的上传非常的不便.也比较多,讲的也是 ...