JNI学习(5)(我是菜鸟)

来源:互联网 发布:电信卡怎么设置4g网络 编辑:程序博客网 时间:2024/06/03 13:22

所有内容为记录学习过程,不是大牛尽情谅解。所有分析都参考深入理解Android 卷一


Java中创建的对象最后由垃圾回收期来回收和释放内存,对于JNI这有什么影响呢?

结合书上的例子分析(下面的例子是他假设的例子并不是真正的源码)

Android_media_MediaScanner_processFile(JNIEnv *env, jobject thiz,jstring path, jstring mimeType, jobject client)

{

。。。。。。;

//保存Java层换入的jobject对象,代表MediaScanner对象

Save_this = thiz;

。。。。。。;

Return;

}

//假设在某个时间,有地方调用callMediaScanner函数

Void callMediaScanner(){

   //在这里操作save_thiz,是否会有问题

}

上面肯定是有问题的,save_thiz对应java层中的MediaScanner 很有可能已经被回收了,也就是说save_thiz保存的jobject 可能已经是野指针。

这里插入一点知识(我也不是太懂)对于一个引用类型的执行操作,它的引用计数不会增加吗?

而垃圾回收机制,只会保证哪些没有被引用过的对象才会被清理。但在JNI中,下面这句不会增加引用计数

save_thiz = thiz; 这种赋值不会增加引用计数

引用计数没有增加 thiz就可能被回收。幸运的是JNI 规范已经很好的解决了这一问题

JNI计数提供了三种引用计数

1Local Reference  本地引用,jni层函数使用的非全局引用对象都是local reference

包括函数调用时传入的jobject和在JNI层函数中创建的jobjectlocal Reference 最大的特点就是 一旦JNI层函数回收,这些jobject就可能被垃圾回收了。

2Global Reference 全局引用,这种对象如不主动释放,它永远不会被垃圾回收。

3WeakGlobal Reference  弱全局引用,一种特殊的Global Reference 在运行过程中可能会被垃圾护手,所以再使用它之前需要用JNIEnvIsSameObject判断是否被回收

看下面代码例子



Ok mClient 不用害怕被回收了


成对出现 你懂得!

想在JNI中保存某个对象 就用 Global Reference 使用完释放就OK了。




这里获取的pathStr 就是一个local Reference 这个函数返回后,该变量就被回收,看上去下面的mEnv->DeleteLocalRefpathStr);看上去是多余的,其实还是有用的。

1,如果不调用哪个DeleteLocalRefpathStr将在函数返回后背回收。

2,如果调用DeleteLocalRef, pathStr会被立即回收,这两者看起来差不多。

但是在某些情况的时候 内存很快就会被耗尽,举例

For(int i = 0;i  < 100 ; i++){

Jstring pathStr = mEnv->NewStringUTF(path);

做一些操作

}

return ;

如果上面哪个循环中不用DeleteLocalRef则会创建100jstring 那么内存耗费就非常可观了。

谁污染谁治理,谁创建谁回收,主动调用还是有好处的,细心每一个细节。





原创粉丝点击