android jni deletelocalref,JNI 引用, DeleteLocalRef使用场景详解
局部引用:
JNI 函数内部创建的 jobject对象及其子类( jclass、 jstring、 jarray等) 对象都是局部引用,它们在 JNI 函数返回后无效;
一般情况下,我们应该依赖 JVM 去自动释放 JNI 局部引用;但下面两种情况必须手动调用 DeleteLocalRef()去释放:
(在循环体或回调函数中)创建大量 JNI 局部引用,即使它们并不会被同时使用,因为 JVM 需要足够的空间去跟踪所有的 JNI 引用,所以可能会造成内存溢出或者栈溢出;
如果对一个大的 Java 对象创建了 JNI 局部引用,也必须在使用完后手动释放该引用,否则 GC 迟迟无法回收该 Java 对象也会引发内存泄漏.
全局引用:
全局引用允许你持有一个 JNI 对象更长的时间,直到你手动销毁;但需要显式调用 NewGlobalRef()和 DeleteGlobalRef():
class MyPeer {
private:
jstring s;
public:
MyPeer(JNIEnv* env, jstring s) {
this->s = env->NewGlobalRef(s);
}
~MyPeer() {
env->DeleteGlobalRef(s);
s = NULL;
}
};
弱全局引用
弱全局引用类似 Java 中的弱引用,它允许对应的 Java 对象被 GC 回收;
类似地,创建和释放也是通过 NewWeakGlobalRef()和 DeleteWeakGlobalRef();
调用 IsSameObject(env, jobj, NULL)可以判断该弱全局引用指向的 Java 对象是否已被 GC 回收。
jobject 对象的引用值不唯一
同一个 jobject对象的不同引用可能拥有不同的值,比如同一 jobject对象每次调用 NewGlobalRef()可能返回不同的值;
要检查两个引用是否指向同一个 jobject对象,必须调用 IsSameObject(),而不要使用 ==去比较;
用于描述一个 jobject对象的 32 位值可能在方法多次调用后发生变化,而两个不同 jobject对象却可能在多次方法调用拥有相同的值,所以千万不能将 jobject对象的值当作 key 使用;
jmethodID 和 jfieldID:
在 JNI 层执行 Java 代码常用到 FindClass()、 GetMethodID()、 GetFieldID();
但只有第一个函数返回的 jclass属于 JNI (局部)引用对象,而 jmethodID和 jfieldID并不是,它们是指向内部 Runtime 数据结构的指针;
实际上这些 ID 是用于缓存的静态对象:第一次查找会做一次字符串比较,但后面再次调用就能直接读取而变得很快;
JVM 会保证这些 ID 是合法的,直到 Class被 unload;
所以, jmethodID和 jfieldID是不需要手动释放的,当然也不能作为 JNI 全局引用。
其他非 JNI 引用:
除了上面提到的 ID,类似 GetStringUTFChars()和 GetByteArrayElements()/ GetCharArrayElements()等函数返回的也是 Raw Data 指针,而非 JNI 引用;
在调用相对应的 ReleaseXXX()函数释放前,它们都是合法的;
批量操作 JNI 引用:
一般情况下要避免大量创建 JNI 局部引用,最好用完后立即释放(实际上目前的实现只预留了 16 个局部引用的空间);
如果确实需要大量操作 JNI 局部引用,要么调用 EnsureLocalCapacity()指定更多的空间,要么调用 PushLocalFrame()/ PopLocalFrame()批量分配/释放:
env->PushLocalFrame(128);
jobjectArray array = env->NewObjectArray(128, gMyClass, NULL);
for (int i = 0; i < 128; ++i) {
env->SetObjectArrayElement(array, i, newMyClass(i));
}
env->PopLocalFrame(array);
开启 CheckJNI 检查 JNI 引用问题:
Android 提供了一种叫做 CheckJNI 的模式用于检测常见的 JNI 错误,其中和 JNI 引用相关的错误有:
将 DeleteGlobalRef()/ DeleteLocalRef()用于错误的 JNI 引用类型;
jfieldID/ jmethodID为空或者类型不合法;
但是 CheckJNI 暂时还不能检测 JNI 局部引用的滥用问题,比如:存储了一个 JNI 局部引用,然后在 JNI 函数返回后继续使用。这种情况很显然应该使用 NewGlobalRef()创建全局 JNI 引用。
开启 CheckJNI 只需一行命令即可:
adb shell setprop debug.checkjni 1
参考:
android jni deletelocalref,JNI 引用, DeleteLocalRef使用场景详解相关推荐
- [免费专栏] Android安全之数据存储与数据安全「详解」
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 Android安全付费专栏长期更新,本篇最新内容请前往: [ ...
- Android系统性能优化(60)---LeakCanary使用详解
Android内存优化(六)LeakCanary使用详解 1.概述 如果使用MAT来分析内存问题,会有一些难度,并且效率也不是很高,对于一个内存泄漏问题,可能要进行多次排查和对比. 为了能够简单迅速 ...
- 【C++】引用以及关联函数(详解)
文章目录 [C++]引用以及关联函数(详解) 1.引用 1.1引用概念 1.2引用的使用 1.3引用的特性 1.4常引用 1.4.1取别名的权限问题: const常量: double和int相互引用: ...
- 转:修改ETM,用Ogre实现《天龙八部》地形与部分场景详解
本文主要讲的是<天龙八部>游戏的地形和一部分场景的具体实现,使用C++, Ogre1.6,我摸索了段时间,可能方法用的并不是最好的,但好歹实现了.文章可能讲得有点罗嗦,很多简单的东西都讲了 ...
- Android四大组件之bindService源码实现详解
Android四大组件之bindService源码实现详解 Android四大组件源码实现详解系列博客目录: Android应用进程创建流程大揭秘 Android四大组件之bindServic ...
- python脚本例子_python dict 字典 以及 赋值 引用的一些实例(详解)
最近在做一个很大的数据库方面的东东,要用到根据数值来查找,于是想到了python中的字典,平时没用过dict这个东东 用的最多的还是 list 和 tuple (网上查 用法一大堆) 看了一下创建字典 ...
- android listview ontouchlistener,Android ListView监听滑动事件的方法(详解)
ListView的主要有两种滑动事件监听方法,OnTouchListener和OnScrollListener 1.OnTouchListener OnTouchListener方法来自View中的监 ...
- java8 方法引用详解_Java8中如何通过方法引用获取属性名详解
前言 在我们开发过程中常常有一个需求,就是要知道实体类中Getter方法对应的属性名称(Field Name),例如实体类属性到数据库字段的映射,我们常常是硬编码指定 属性名,这种硬编码有两个缺点. ...
- Android 事件分发机制分析及源码详解
Android 事件分发机制分析及源码详解 文章目录 Android 事件分发机制分析及源码详解 事件的定义 事件分发序列模型 分发序列 分发模型 事件分发对象及相关方法 源码分析 事件分发总结 一般 ...
- android edittext 过滤英文名称,Android 限制edittext 整数和小数位数 过滤器(详解)
写了一个过滤器,根据需要限制edittext输入的整数和小数位,如下代码: package allone.verbank.apad.client.component; import android.t ...
最新文章
- 4岁学编程,19岁创办以太坊,4年十亿身家!
- JQuery学习笔记02-选择器把需要的东西揪出来(基础)
- mysql 导入文件提示 --secure-file-priv option 问题
- the graphics window has detected an error and is not able to ini
- Python-GUI编程PyQT5案例:注册界面扇形菜单动画及相关事件处理
- Docker技术快速精通指南
- 思科虚拟机配置dhpc服务器,思科模拟器配置DHCP
- 如何获取系统的临时目录路径?
- 开源、高质量QR码多语言生成库
- Bootstrap 两端对齐的导航
- 删除归档_备份与归档的“罗生门”
- 服务器远程登陆最大连接数,解决登录Windows服务器时超出了最大允许连接数
- BZOJ1588: [HNOI2002]营业额统计
- 设计模式-----桥接模式(Bridge Pattern)(转)
- mysql内连接和左连接的区别_MySQL连接查询 内连接和外连接的区别
- hfs网络文件服务器如何设置,hfs网络文件服务器的教程
- linux运行脚本运行不了,shell脚本在windows上可以执行,Linux上面不能执行
- HTML+CSS+JS网站设计——上海美食(8页) 酒水网页设计作业,甜品美食网页制作作业, 学生零食网页作业
- Android中Intent的介绍
- 计算机硬盘隐,终极电脑磁盘隐藏方法大全