对于native层new出来的c++对象的生命周期的管理,Android通过对这个对象引用计数的方式实现对象生命周期的管理(自动析构和释放内存)。为此Android提供了两个引用计数帮助类:sp,wp。sp,wp都是模板类,模板参数就是继承了RefBase的子类。sp代表强引用,wp代表弱引用。根据生命周期的管理策略(比如对象的周期受强引用计数管理,或者受强引用和弱引用共同管理)的不同,这两种引用对对象生命周期的影响有所不同。


RefBase的类图如下:

RefBase中保存着一个指向weakref_impl类的指针。通过weakref_impl的成员变量保存着RefBase类的引用计数。mStrong表示强引用计数的个数,mWeak表示弱引用计数的个数。假设有如下的代码:

class A:public RefBase {public:    A() {        cout<<"constructor A"<
以上代码通过new的方式产生出来的A的对象的强引用计数和弱引用计数为2,即weakref_imp中mStrong和mWeak的值为2. 当new A()完成的时候,A的基类RefBase还new了一个weakref_iml对象,用来记录A的强弱引用计数。当把new A()所产生的A*指针作为参数构造一个sp对象的时候,在sp的copy constructor中会调用A的incStrong()方法,这个方法中先增加A的弱引用计数一次,然后增加强引用计数一次,强弱引用计数此时为1.当把pA1作为参数调用sp  的赋值函数产生出pA2的时候,在赋值函数中再次调用A的基类RefBase的incStrong函数,这样强弱引用计数就变为了2.

过了pA1的作用域之后,pA1的析构函数被调用,在析构函数中会调用A的decStrong函数减少一次强弱引用计数。同理,过了pA2的作用域之后,也会减少一次强弱引用计数,这时,强弱引用计数就变为了0.在RefBase类的decStrong函数中会做判断,当引用计数为1的时候,表明本次调用后,强引用计数会为0,如果对象的生命周期只受强引用计数管理,这个时候就会调用delete来释放自己的内存。


从上面的分析来看,如果对象的生命周期只受强引用计数管理(默认如此),当对象的强引用计数为0的时候就会delete掉这个对象,而不管弱引用计数的值,当弱引用计数为0的时候就会delete掉weakref_imp类。那么弱引用计数究竟有什么作用呢,当调用了RefBase的extendObjectLifetime方法,参数为OBJECT_LIFETIME_WEAK,这将改变对象的生命周期的管理策略为强弱引用计数同时决定何时delete对象。


一般而言,程序代码中最好只有一个地方是采取sp的方式保存着new出来对象的地址,其他的用处用wp。这样对象的生命周期只受一处管理,其他地方通过wp来使用A的时候,先通过promote()函数看所保存的对象是否已经被释放。如果没有被释放,就可以返回一个sp类供调用者使用。


在实际使用中要注意的是:时刻要清楚自己new出来的对象的引用计数的次数。清楚自己对sp,wp构造,赋值等操作对引用计数的影响。比如有以下代码:

{sp pA1 = new A();pA1->decStrong();}
那么在花括号的作用域之后,程序会崩溃。原因如下:

第一句,强引用和弱引用计数为1.

第二句,强引用计数为为0,弱引用计数为0,A的对象被delete;但是sp中还是保存着A的指针;

过了作用域之后,pA1的析构函数被调用,这个时候会再次通过pA1中保存的A的指针调用decStrong函数。但是此时,A的对象已经被delete。

所以程序崩溃。

下面是sp,wp与RefBase的类图关系:



更多相关文章

  1. Android的内存机制和常见泄漏情形
  2. Android的内存泄漏和调试
  3. Android(安卓)内存管理 &Memory Leak & OOM 分析
  4. Android高手进阶教程(二十五)之---Android(安卓)中的AIDL!!!
  5. Android中AsyncTask(异步任务)和Handler(线程消息机制)的详解
  6. 2019AndroidBAT.字节跳动74道高级面试第二篇
  7. Android,谁动了我的内存(1)
  8. Android在网络中与JavaWeb的项目进行交互的方法
  9. Android通过Socket(TCP/IP)与PC通讯

随机推荐

  1. 【JavaScript&JQuery】原生API实现li标签
  2. 从JDK源码角度看并发竞争的超时
  3. APNS开源包的内存泄露问题
  4. 编写自己的代码库(javascript常用实例的实
  5. 【9.0】对于java集合的迭代器的底层分析
  6. GenericObjectPool对象池异常排查
  7. Java的HelloWorld程序的真正用法
  8. Java普通代码块,构造代码块,静态代码块区别
  9. Java操作数据库之jdbc【原生方式】
  10. java数据结构--链表