JNI由浅入深_8_JNI缓存字段和方法ID
获取字段ID和方法ID时,需要用字段、方法的名字和描述符进行一个检索。检索过程相对比较费时,因此本节讨论用缓存技术来减少这个过程带来的消耗。缓存字段ID和方法ID的方法主要有两种。两种区别主要在于缓存发生的时刻,是在字段ID和方法ID被使用的时候,还是定义字段和方法的类静态初始化的时候。
1、使用时缓存
字段ID和方法ID可以在字段的值被访问或者方法被回调的时候缓存起来。下面的代码中把字段ID存储在静态变量当中,这样当本地方法被重复调用时,不必重新搜索字段ID。
JNIEXPORT void JNICALL
Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj)
{
static jfieldID fid_s = NULL; /* cached field ID for s */ jclass cls = (*env)->GetObjectClass(env, obj);
jstring jstr;
const char *str; if (fid_s == NULL) {
fid_s = (*env)->GetFieldID(env, cls, "s",
"Ljava/lang/String;");
if (fid_s == NULL) {
return; /* exception already thrown */
}
} printf("In C:\n"); jstr = (*env)->GetObjectField(env, obj, fid_s);
str = (*env)->GetStringUTFChars(env, jstr, NULL);
if (str == NULL) {
return; /* out of memory */
}
printf(" c.s = \"%s\"\n", str);
(*env)->ReleaseStringUTFChars(env, jstr, str); jstr = (*env)->NewStringUTF(env, "123");
if (jstr == NULL) {
return; /* out of memory */
}
(*env)->SetObjectField(env, obj, fid_s, jstr);
}
2、初始化缓存
许多情况下,在字段ID和方法ID被使用前就初始化是很方便的。VM在调用一个类的方法和字段之前,都会执行类的静态初始化过程,所以在静态初始化该类的过程中计算并缓存字段ID和方法ID是个不错的选择。
例如,为了缓存InstanceMethodCall.callback的方法ID,我们引入了一个新的本地方法initIDs,这个方法在InstanceMethodCall的静态初始化过程中被调用。
/**
* 缓存ID
*/
jmethodID callbackStatic; JNIEXPORT void JNICALL Java_com_example_jniandroid_service_CFunction_callJniNative2(
JNIEnv * env, jobject obj) {
LOGI("缓存了id...");
(*env)->CallStaticVoidMethod(env, obj, callbackStatic);
} JNIEXPORT void JNICALL Java_com_example_jniandroid_service_CFunction_initIDS(
JNIEnv * env, jobject obj) {
//调用静态方法
jclass cls = (*env)->GetObjectClass(env, obj);
callbackStatic = (*env)->GetStaticMethodID(env, cls, "callbackStatic", "()V");
}
两种缓存ID的方式之间的对比
如果JNI程序员不能控制方法和字段所在的类的源码的话,在使用时缓存是个合理的方案。例如在MyNewString当中,我们不能在String类中插入一个initIDs方法。
比起静态初始时缓存来说,使用时缓存有一些缺点:
1、使用时缓存的话,每次使用时都要检查一下。
2、方法ID和字段ID在类被unload时就会失效,如果你在使用时缓存ID,你必须确保只要本地代码依赖于这个ID的值,那么这个类不被会unload(下一章演示了如何通过使用JNI函数创建一个类引用来防止类被unload)。另一方面,如果缓存发生在静态初始化时,当类被unload和reload时,ID会被重新计算。
因此,尽可能在静态初始化时缓存字段ID和方法ID。
JNI由浅入深_8_JNI缓存字段和方法ID的更多相关文章
- Android 通过 JNI 访问 Java 字段和方法调用
在前面的两篇文章中,介绍了 Android 通过 JNI 进行基础类型.字符串和数组的相关操作,并描述了 Java 和 Native 在类型和签名之间的转换关系. 有了之前那些基础,就可以实现 Jav ...
- JNI由浅入深_9_JNI 异常处理
1 .本地代码中如何缓存和抛出异常 下面的代码中演示了如何声明一个会抛出异常的本地方法.CatchThrow这个类声明了一个会抛出IllegalArgumentException异常的名叫doit的本 ...
- JNI由浅入深_4_JNI基础知识详解
Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 ...
- JNI系列——C文件中的方法调用Java中方法
1.创建xxx.jni包并在该包下实现一些Java的方法,和要调用的本地方法 2.实现MainActivity中的按钮点击事件-即点击按钮调用本地的方法 3.在C文件中的方法中回调Java的方法 3. ...
- 使用反射创建Bean、Spring中是如何根据类名配置创建Bean实例、Java提供了Class类获取类别的字段和方法,包括构造方法
Java提供了Class类,可以通过编程方式获取类别的字段和方法,包括构造方法 获取Class类实例的方法: 类名.class 实例名.getClass() Class.forNam ...
- [SQL]查询整个数据库中某个特定值所在的表和字段的方法
查询整个数据库中某个特定值所在的表和字段的方法 当数据库做的太庞大的时候,难免会出现忘记哪个值会存入哪个表的情况,于是在网上找到的如下解决办法. 通过做一个存储过程,只需要传入一个想要查找的值,即可查 ...
- JNI由浅入深_6_简单对象的应用
1.声明native方法 public class ComplexObject { /** * 返回一个对象数组 * @param val * @return */ public native Per ...
- MySQL中同时存在创建和更新时间戳字段解决方法浅析
MySQL中同时存在创建和更新时间戳字段解决方法浅析 明确我的MySQL版本.mysql> SELECT VERSION();+------------+| VERSION() |+------ ...
- Vue计算属性缓存(computed) vs 方法
Vue计算属性缓存(computed) vs 方法 实例 <div id="example"> <p>Original message: "{{ ...
随机推荐
- 关于iFrame特性总计和iFrame跨域解决办法
1.iframe 定义和用法 iframe 元素会创建包含另外一个文档的内联框架(即行内框架). HTML 与 XHTML 之间的差异 在 HTML 4.1 Strict DTD 和 XHTML 1. ...
- python中单下划线和双下滑线
使用单下划线(_one_underline)开头表示方法不是API的一部分,不要直接访问(虽然语法上访问也没有什么问题). 使用双下划线开头(__two_underlines)开头表示子类不能覆写该方 ...
- MyEclipse打包带源码的jar包
平时开发中,我们喜欢将一些类打包成jar包,然后在别的项目中继续使用,不过由于看不到jar包里面的类的源码了,所以也就无法调试,要想调试,那么就只能通过关联源代码的形式,这样或多或少也有一些不方便,今 ...
- line-height和height的区别
line-height 是指每行的高度, 假如定义p标签的行高为line-heigth:20px; 文字在浏览器中显示为一行时,这个p标签的高度会为20px,如果为两行,则p标签的高度为40px; l ...
- C#-创建并添加TXT文件
public static void WriteToText(string txtContent, string txtPath) { using (FileStream fs = new FileS ...
- Android Weekly Notes Issue #244
Android Weekly Issue #244 February 12th, 2017 Android Weekly Issue #244 本期内容包括: Android Fragments使用教 ...
- 前端单元测试环境搭建 Karma Jasmine
Karma 官网On the AngularJS team, we rely on testing and we always seek better tools to make our life e ...
- linux socket中tcp的time_wait的快速回收和重用
解决方法: 我们可以通过调整内核参数来调整: vi /etc/sysctl.conf 编辑文件,加入以下内容: net.ipv4.tcp_syncookies = net.ipv4.tcp_tw_re ...
- QTableview 获取鼠标坐标的item(QModelIndex)
要实现的功能是QTableview中Item项上右键弹出菜单这就必然要判断点击右键时鼠标指针是否在QTableView的Item上 如果是QTableWidget可以用itemAt来判断QTableV ...
- zabbix连不上数据库
[root@localhost etc]# tail -f /var/log/zabbix_server.log 1267:20130722:195451.493 [Z3001] connection ...