JNI 编程实现了 native code 和 Java 程序的交互,因此 JNI 代码编程既遵循 native code 编程语言的编程规则,同时也遵守 JNI 编程的文档规范。在内存管理方面,native code 编程语言本身的内存管理机制依然要遵循,同时也要考虑 JNI 编程的内存管理。

本章简单概括 JNI 编程中显而易见的内存泄漏。从 native code 编程语言自身的内存管理,和 JNI 规范附加的内存管理两方面进行阐述。

Native Code 本身的内存泄漏

JNI 编程首先是一门具体的编程语言,或者 C 语言,或者 C++,或者汇编,或者其它 native 的编程语言。每门编程语言环境都实现了自身的内存管理机制。因此,JNI 程序开发者要遵循 native 语言本身的内存管理机制,避免造成内存泄漏。以 C 语言为例,当用 malloc() 在进程堆中动态分配内存时,JNI 程序在使用完后,应当调用 free() 将内存释放。总之,所有在 native 语言编程中应当注意的内存泄漏规则,在 JNI 编程中依然适应。

Native 语言本身引入的内存泄漏会造成 native memory 的内存,严重情况下会造成 native memory 的 out of memory。

Global Reference 引入的内存泄漏

JNI 编程还要同时遵循 JNI 的规范标准,JVM 附加了 JNI 编程特有的内存管理机制。

JNI 中的 Local Reference 只在 native method 执行时存在,当 native method 执行完后自动失效。这种自动失效,使得对 Local Reference 的使用相对简单,native method 执行完后,它们所引用的 Java 对象的 reference count 会相应减 1。不会造成 JavaHeap 中 Java 对象的内存泄漏。

而 Global Reference 对 Java 对象的引用一直有效,因此它们引用的 Java 对象会一直存在 Java Heap 中。程序员在使用 Global Reference 时,需要仔细维护对Global Reference 的使用。如果一定要使用 Global Reference,务必确保在不用的时候删除。就像在 C 语言中,调用 malloc() 动态分配一块内存之后,调用 free()释放一样。否则,Global Reference 引用的 Java 对象将永远停留在 Java Heap 中,造成 Java Heap 的内存泄漏。

1、什么需要释放? 

什么需要什么呢 ? JNI 基本数据类型是不需要释放的 , 如 jint , jlong , jchar 等等 。 我们需要释放是引用数据类型,当然也包括数组家族。如:jstring,jobject ,jobjectArray,jintArray 等等。

当然,大家可能经常忽略掉的是 jclass ,jmethodID , 这些也是需要释放的哦

2、如何去释放?

1)      释放String

jstring jstr = NULL;

char* cstr = NULL;

//调用方法

jstr = (*jniEnv)->CallObjectMethod(jniEnv, mPerson, getName);

cstr = (char*) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);

__android_log_print(ANDROID_LOG_INFO, "JNIMsg", "getName  ---- >  %s",cstr );

//释放资源

(*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);

(*jniEnv)->DeleteLocalRef(jniEnv, jstr);

2)      释放 类 、对象、方法

(*jniEnv)->DeleteLocalRef(jniEnv, XXX);

“XXX” 代表 引用对象

3)      释放 数组家族

jobjectArray arrays = NULL;

jclass jclsStr = NULL;

jclsStr = (*jniEnv)->FindClass(jniEnv, "java/lang/String");

arrays = (*jniEnv)->NewObjectArray(jniEnv, len, jclsStr, 0);

(*jniEnv)->DeleteLocalRef(jniEnv, jclsStr);  //释放String类

(*jniEnv)->DeleteLocalRef(jniEnv, arrays); //释放jobjectArray数组

native method 调用 DeleteLocalRef() 释放某个 JNI Local Reference 时,首先通过指针 p 定位相应的 Local Reference 在 Local Ref 表中的位置,然后从Local Ref 表中删除该 Local Reference,也就取消了对相应 Java 对象的引用(Ref count 减 1)。

参考文章:在 JNI 编程中避免内存泄漏

解决办法:释放所有对object的引用

jnienv->SetByteArrayRegion(audioArray,0,frameSize,(jbyte*)fReceiveBuffer);
       jnienv->DeleteLocalRef(audioArray);

1.FindClass

jclass ref= (env)->FindClass("java/lang/String");

env->DeleteLocalRef(ref);

例如,

jstring (*NewString)(JNIEnv*, const jchar*, jsize); const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*);
jstring (*NewStringUTF)(JNIEnv*, const char*); const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
env->DeleteLocalRef(ref);
jclass ref = env->GetObjectClass(robj);

env->DeleteLocalRef(ref);
jbyte* array= (*env)->GetByteArrayElements(env,jarray,&isCopy);

(*env)->ReleaseByteArrayElements(env,jarray,array,0);

5.const char* input =(*env)->GetStringUTFChars(env,jinput, &isCopy);

(*env)->ReleaseStringUTFChars(env,jinput,input);

 jobject     (*NewGlobalRef)(JNIEnv*, jobject);     

void        (*DeleteGlobalRef)(JNIEnv*, jobject);
jobject ref= env->NewGlobalRef(customObj);

env->DeleteGlobalRef(customObj);

JNI 资源释放的更多相关文章

  1. 基于 Android NDK 的学习之旅-----资源释放

    做上一个项目的时候因为与C引擎交互频繁,有时候会突然莫名其妙的的整个应用程序直接挂掉.因为我是学Java 开始的,所以对主动释放内存没多大概念(GC直接帮忙回收),后查询原因才知道是因为JNI 有些对 ...

  2. 基于webrtc的资源释放问题(二)

    基于webrtc的资源释放问题(二) ——建立连接的过程中意外中断 应用背景: 我们在打电话的时候会不会遇到这种情况?打电话的时候未接通之前挂掉了电话,或者在接通之后建立的连接的过程中挂掉电话? 特别 ...

  3. 基于webrtc的资源释放问题(一)

    基于webrtc的资源释放问题(一) ——重复释放webrtc的相关资源 背景: 视频通讯大都只是作为一个功能存在于各种应用中,比如微信,qq .既然只是应用的一部分,这样就涉及反复的开启和关闭视频通 ...

  4. C#资源释放

    转自:http://www.cnblogs.com/psunny/archive/2009/07/07/1518812.html 深刻理解C#中资源释放 今天我的一个朋友看到我写的那篇<C#中用 ...

  5. TList,TObjectList 使用——资源释放

    TOjectList = Class (Tlist); TOjectList继承Tlist,从名字上看就可以知道它是专门为对象列表制作的,那么他到底丰富了那些功能呢? 首先是 TObject 作为对象 ...

  6. Delphi中关于资源释放(Free,Relealse,FreeAndNil)

    根据日常编程经验,得出一些Delphi中关于资源释放的体会. 假如有对象Obj为TObject类型: 1) Obj.Free直接释放资源后,调用OnDestroy事件,但是没有将Obj指针值置为Nil ...

  7. 深刻理解C#中资源释放

    今天我的一个朋友看到我写的那篇<C#中用AJAX验证用户登录>时,给我指出了点小毛病.就是在用户登录时,如果用户登录失败,在下面这段代码中,都会new出来一个User对象,如果连续登录失败 ...

  8. Unity3d: 资源释放时存储空间不足引发的思考和遇到的问题

    手机游戏第一次启动基本上都会做资源释放的操作,这个时候需要考虑存储空间是否足够,但是Unity没有自带获取设备存储空间大小的 接口,需要调用本地方法分别去android或ios获取,这样挺麻烦的.而且 ...

  9. .net 资源释放(托管资源和非托管资源)

    1.托管资源 像int.float.DateTime等都是托管资源:net中80%的资源都是托管资源: 托管资源的回收通过GC(垃圾回收器)自动释放分配给该对象的内存,但无法预测进行垃圾回收的时间,我 ...

随机推荐

  1. Maven多模块项目搭建

    最近一直在思考如何能够更好的重用代码.减少重复劳动,之前有一篇文章通过导入JAR包的形式,可以重用部分形如util类的方法,但是这样的话,管理起来jar包,特别是协同工作,多项目情况下,管理JAR会出 ...

  2. [Angular] Provide Feedback to Progress Events with Angular’s HttpRequest Object

    In some cases your application might need to upload large amounts of data, such as files. Obviously ...

  3. leetCode 72.Edit Distance (编辑距离) 解题思路和方法

    Edit Distance Given two words word1 and word2, find the minimum number of steps required to convert  ...

  4. 关于iOS7中UIView效果失效问题的解决

    最近想做一个跑马灯的效果.于是写出了例如以下的跑马灯效果的代码...可是调试发现,在iOS6下动画是能够运行的,可是在iOS7下动画并不运行,没有达到预期的效果. [_scrollLabel size ...

  5. mysql安装,数据库连接

    安装教程http://jingyan.baidu.com/article/e3c78d64412ae83c4c85f5fd.html 首先打开MySQL官网,找到Downloads标签,点击进入.如果 ...

  6. JAVA设计模式之【代理模式】

    代理模式 通过代理对象间接访问 代购 客户端不想或者不能直接访问一个对象,可以通过一个称为代理的第三者来实现间接访问,该方案称为代理模式 角色 抽象主题角色Subject 声明真实主题类与代理类的公共 ...

  7. DB-MySQL:目录

    ylbtech-DB-MySQL:目录 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbt ...

  8. POJ 3188暴搜

    题意: 思路: 裸的暴搜 --. 但是要注意如果你不用所有的按键就能输出最优解的话一定要把所有的字母都安排到一个位置-. 我的一群PE就是这么来的-- 为什么写的人这么少-- // by Sirius ...

  9. mysql导入数据,涉及到时间转换,乱码问题解决

    表结构: drop table if exists `qi_an_log`;CREATE TABLE `qian_log` (`dt` LONG NOT NULL COMMENT '产生日期,格式yy ...

  10. 【DNN 系列 创建WEB模块 项目】

    现在DNN已经更新到8.0.3 然而使用7.0 的项目模块 会报错, 就是填写网站的时候 会再网站的项目当中添加文件夹这样会破坏网站 所以来自己创建自己的模板项目 首选创建空的WEB 项目网站 创建完 ...