| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> JNI内存方面说明以及相关类型手动释放内存 -> 正文阅读 |
|
[移动开发]JNI内存方面说明以及相关类型手动释放内存 |
JNI内存方面说明以及相关类型手动释放内存 6.1 Local Reference 不是 native code 的局部变量 一、Java内存?Java程序所涉及的内存可以从逻辑上划分为两部分:Heap Memory和Native Memory。 1)Heap Memory: 供Java应用程序使用的,所有java对象的内存都是从这里分配的,它不是物理上连续的,但是逻辑上是连续的。可通过java命令行参数“-Xms, -Xmx”大设置Heap初始值和最大值。
????????在Android系统对于每个应用都有内存使用的限制,机器的内存限制,在/system/build.prop文件中配置的。可以在manifest文件application节点加入? 2)Native Memory: 也称为C-Heap,供Java Runtime进程使用的,没有相应的参数来控制其大小,其大小依赖于操作系统进程的最大值。 Java应用程序都是在Java Runtime Environment(JRE)中运行,而Runtime本身就是由Native语言(如:C/C++)编写程序。Native Memory就是操作系统分配给Runtime进程的可用内存,它与Heap Memory不同,Java Heap 是Java应用程序的内存。(JVM只是JRE的一部分,JVM的内存模型属于另一话题) Native Memory的主要作用如下:
由上可以得知,JNI内存分配其实与Native Memory有很大关系。 二、JNI内存和引用?在Java代码中,Java对象被存放在JVM的Java Heap,由垃圾回收器(Garbage Collector,即GC)自动回收就可以。 在Native代码中,内存是从Native Memory中分配的,需要根据Native编程规范去操作内存。如:C/C++使用malloc()/new分配内存,需要手动使用free()/delete回收内存。 然而,JNI和上面两者又有些区别。 JNI提供了与Java相对应的引用类型(如:jobject、jstring、jclass、jarray、jintArray等),以便Native代码可以通过JNI函数访问到Java对象。引用所指向的Java对象通常就是存放在Java Heap,而Native代码持有的引用是存放在Native Memory中。 举个例子,如下代码:
1)jstring类型是JNI提供的,对应于Java的String类型。 2)JNI函数NewStringUTF()用于构造一个String对象,该对象存放在Java Heap中,同时返回了一个jstring类型的引用。 3)String对象的引用保存在jstr中,jstr是Native的一个局部变量,存放在Native Memory中。 ????开发人员都应该遇到过OOM(Out of Memory)异常,在JNI开发中,该异常可能发生在Java Heap中,也可能发生在Native Memory中。
????Java Heap 中出现?Out of Memory异常的原因有两种: ????1)程序过于庞大,致使过多 Java 对象的同时存在; ????2)程序编写的错误导致 Java Heap 内存泄漏。 ????Native Memory中出现?Out of Memory异常的原因: ????1)程序申请过多资源,系统未能满足,比如说大量线程资源; ????2)程序编写的错误导致Native Memory内存泄漏。 ????为了避免出现OOM异常和内存泄露,我们在进行JNI开发的时候,需要熟悉它的内存分配和管理。 ????JNI引用有三种:Local Reference、Global?Reference、Weak?Global?Reference。下面分别来介绍一下这三种引用内存分配和管理。 三、Local Reference? ? 只在Native Method执行时存在,只在创建它的线程有效,不能跨线程使用。它的生命期是在Native Method的执行期开始创建(从Java代码切换到Native代码环境时,或者在Native Method执行时调用JNI函数时),在Native Method执行完毕切换回Java代码时,所有Local Reference被删除(GC会回收其内存),生命期结束(调用 ?实际上,每当线程从Java环境切换到Native代码环境时,JVM 会分配一块内存用于创建一个 Local Reference 表、Local Reference 和 Java 对象的关系 接下来举个简单例子说明一下:
? ?在Native Method结束时,JVM会自动释放Local Reference,但
? ?在C/C++中实例化的JNI对象,如果不返回java,必须用release掉或delete,否则内存泄露。包括NewStringUTF,NewObject。对于一般的基本数据类型(如:jint,jdouble等),是没必要调用该函数删除掉的。如果返回java不必delete,java会自己回收。 四、Global Reference? ? Local Reference是在Native Method执行的时候出现的,而
? ? 使用? 五、Weak Global Reference? ? 用 ? ? 对 六、注意点6.1 Local Reference 不是 native code 的局部变量? ? 很多人会误将 JNI 中的 Local Reference 理解为 Native Code 的局部变量。这是错误的。 ? ? Native Code 的局部变量和 Local Reference 是完全不同的,区别可以总结为: ⑴局部变量存储在线程堆栈中,而 Local Reference 存储在 Local Ref 表中。 ⑵局部变量在函数退栈后被删除,而 Local Reference 在调用 DeleteLocalRef() 后才会从 Local Ref 表中删除,并且失效,或者在整个 Native Method 执行结束后被删除。 ⑶可以在代码中直接访问局部变量,而 Local Reference 的内容无法在代码中直接访问,必须通过 JNI function 间接访问。JNI function 实现了对 Local Reference 的间接访问,JNI function 的内部实现依赖于具体 JVM。 6.2 注意释放所有对jobject的引用:
其它的还有:
因为根据
? ? jclass也是jobject。而 6.3 局部引用和全局引用的转换? ? 注意Local Reference的生命周期,如果在Native中需要长时间持有一个Java对象,就不能使用将jobject存储在Native,否则在下次使用的时候,即使同一个线程调用,也将会无法使用。下面是错误的做法:
正确的做法是使用Global Reference,如下:
6.4 多线程? ? JNIEnv和jobject对象都不能跨线程使用。 对于jobject,解决办法是:
? ? 对于JNIEnv,解决办法是在每个线程中都重新生成一个env
? ? 当在一个线程里面调用AttachCurrentThread后,如果不需要用的时候一定要DetachCurrentThread,否则线程无法正常退出,导致JNI环境一直被占用。 七、手动释放内存7.1 那些需要手动释放?·不需要手动释放(基本类型):jint,jlong,jchar,jdouble等 ·需要手动释放(引用类型,数组家族):jstring,jobject,jobjectArray,jintArray,jclass等 7.2 释放方法7.2.1 jstring&char*
?7.2.2 jobject,jobjectArray,jclass 等引用类型
7.2.3 jbyteArray
7.2.4 GetByteArrayElements
7.2.5 NewGlobalRef
7.3?避免内存泄露? ? JNI如果创建以上引用却不手动释放的话很容易就造成内存泄露,所以JNI编程创建的引用类型一定要手动释放(切身教训),检测内存泄露可以使用 参考文章 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/31 9:45:57- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |