Android的framework层都是由c++来实现的 大家都知道c++最令人头痛的莫过于内存泄漏了 ,如果是一个人开发还好 当new出来一个对象后 应该会记得delete掉 但是当多人开发的时候难免会出现这里调用了 那里忘记释放了 特别是对于Android是一个系统来说 那就更加了! 所以才有了用智能指针来处理这个问题,当没有地方引用的时候实现自动释放 避免内存泄漏或者野指针的问题。
在分析源码的过程中时常会出现sp<T>之类的出现 那现在就来看看它的具体实现。
首先我们来看看:
template <class T> class LightRefBase { public: inline LightRefBase() : mCount(0) { }//初始化引用的次数为0 inline void incStrong(const void* id) const {//增加一次引用 android_atomic_inc(&mCount);//原子操作 由汇编语言完成 } inline void decStrong(const void* id) const {//减少一次引用 if (android_atomic_dec(&mCount) == 1) { delete static_cast<const T*>(this); } } //获取该对象当前被引用的次数 inline int32_t getStrongCount() const { return mCount; } typedef LightRefBase<T> basetype; protected: inline ~LightRefBase() { }//析构 private: mutable volatile int32_t mCount;//用来记录对象的引用次数 };
template <typename T> class sp { public: inline sp() : m_ptr(0) { }//默认构造函数 初始化m_ptr为0 sp(T* other);//初始化T 这里的T代表是实际引用的对象 sp(const sp<T>& other);//拷贝构造函数 同理 template<typename U> sp(U* other);//带有返回值的构造函数 template<typename U> sp(const sp<U>& other); ~sp(); // 操作符重载 sp& operator = (T* other); sp& operator = (const sp<T>& other); template<typename U> sp& operator = (const sp<U>& other); template<typename U> sp& operator = (U* other); //动态来设置T的对象 void force_set(T* other); // Reset void clear(); // 操作符重载 这样的话当使用这些操作符 返回的就是引用的实际对象 inline T& operator* () const { return *m_ptr; } inline T* operator-> () const { return m_ptr; } inline T* get() const { return m_ptr; } // 宏定义 一些运算符 COMPARE(==) COMPARE(!=) COMPARE(>) COMPARE(<) COMPARE(<=) COMPARE(>=) private: template<typename Y> friend class sp; template<typename Y> friend class wp;//友元类 void set_pointer(T* ptr); T* m_ptr;//这里的T就是实际引用的对象了 };再来看看他的构造函数和拷贝构造
template<typename T> sp<T>::sp(T* other)//这里的other实际就是LigthRefBase : m_ptr(other)//把other赋值给m_ptr { if (other) other->incStrong(this);//调用LigthRefBase的incstrong } template<typename T> sp<T>::sp(const sp<T>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this);//同上面构造函数 }
template<typename T> sp<T>::~sp() { if (m_ptr) m_ptr->decStrong(this);//实际是调用LightRefBase的decStrong函数-1了 如果引用次数为0则delete该对象 }
#include <stdio.h> #include <utils/RefBase.h> using namespace android; class MyLightClass : public LightRefBase<MyLightClass> { public: MyLightClass() { printf("开始调用构造函数\n"); } virtual ~MyLightClass() { printf("析构\n"); } }; int main(int argc, char** argv) { MyLightClass* light = new MyLightClass(); sp<LightClass> lp = light; printf("当前的引用次数为%d\n", light->getStrongCount()); { sp<LightClass> lp2 = lp; <span style="font-family: Arial, Helvetica, sans-serif;">printf("当前的引用次数为%d\n", light->getStrongCount());</span> } <span style="font-family: Arial, Helvetica, sans-serif;">printf("当前的引用次数为%d\n", light->getStrongCount());</span> return 0; }现在来分析下我们写的代码 当执行到 sp<LightClass> lp=light 时会自动调用sp的构造函数初始化里面的m_ptr为LinghtClass的实际对象 进而调用LightRefBase里面的incStrong方法使引用计数m_count加一操作,所以此时打印的应该是1,然后在进入内嵌代码块 执行sp<LightClass> lp2=lp; 同样会执行加1操作 所以在打印的时候应该是2了,当执行完代码块里面的内容后 由于是局部变量保存在栈中 当执行完了以后所以就会自动掉用sp的析构函数 那么此时应该会调用LightRefBase的decStrong函数-1操作了 并且判断下当前是引用计数是不是为0 由于不为0 表明还有对象在用所以不会删除此对象 ,出了代码块再打印那么应该是1了,当我们执行完这个程序退出时候那么lp的局部变量会再次调用sp的析构函数 在把引用计数-1 然后判断当前是否为0 此时满足条件 所以就会delete此对象 也就是我们new的 light对象了;我们在 external目录新建此文件为 MyLightClass.cpp
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_MODULE := mylight LOCAL_SRC_FILES := MyLightClass.cpp LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils include $(BUILD_EXECUTABLE)
xielinhua@ubuntu:~/Downloads/Android$ mmm ./external/mylight
xielinhua@ubuntu:~/Downloads/Android$make snod
xielinhua@ubuntu:~/Downloads/Android$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage &最后来执行我们刚才写的程序看看他的打印是不是我们刚才分析的一样呢:
xielinhua@ubuntu:~/Downloads/Android$ adb shell
root@android:/ # cd system/bin/ root@android:/system/bin # ./mylight 开始调用构造函数 当前次数为1 当前次数为2 当前次数为1 析构
class RefBase { public: void incStrong(const void* id) const;//增加一个引用计数 void decStrong(const void* id) const;//减少一个引用计数 void forceIncStrong(const void* id) const; class weakref_type//内部类 主要是通过这个类来实现强弱引用的计数 { public: RefBase* refBase() const;//实际对象 void incWeak(const void* id); void decWeak(const void* id);//减少弱引用的次数 bool attemptIncStrong(const void* id); //! This is only safe if you have set OBJECT_LIFETIME_FOREVER. bool attemptIncWeak(const void* id); }; weakref_type* createWeak(const void* id) const;//创建一个管理引用的对象 weakref_type* getWeakRefs() const; protected: RefBase(); virtual ~RefBase(); //! Flags for extendObjectLifetime()对象的生命周期控制 默认为0则代表是受强引用的控制 enum { OBJECT_LIFETIME_WEAK = 0x0001,//代表受弱引用的控制 OBJECT_LIFETIME_FOREVER = 0x0003//代表不受控制 自己来管理 }; void extendObjectLifetime(int32_t mode);//改变对象的生命周期的控制 //! Flags for onIncStrongAttempted() enum { FIRST_INC_STRONG = 0x0001 }; virtual void onFirstRef();//第一次强引用 子类可以重写该方法初始化一些东西 virtual void onLastStrongRef(const void* id);//最后一次强引用了 说明该对象可能会释放掉 virtual bool onIncStrongAttempted(uint32_t flags, const void* id); virtual void onLastWeakRef(const void* id); private: friend class weakref_type; class weakref_impl; RefBase(const RefBase& o); RefBase& operator=(const RefBase& o); weakref_impl* const mRefs;//看名字就知道weakref_type的实现类 };
RefBase::RefBase() :mRefs(new weakref_impl(this))//构造的时候 new了一个weakref_impl对象 { //mRefs是RefBase的成员变量,类型是weakref_impl }
weakref_impl(RefBase* base) :mStrong(INITIAL_STRONG_VALUE) //强引用计数,初始值为0x1000000 ,mWeak(0) //弱引用计数,初始值为0 ,mBase(base)//所指向的实际对象 ,mFlags(0)//生命周期受什么影响 默认是0 也就是强引用 ,mStrongRefs(NULL) ,mWeakRefs(NULL) ,mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT) ,mRetain(false) { }我们再来举一个列子:
A a=new A(); sp<A> sa=a;
template<typename T> sp<T>::sp(T* other) : m_ptr(other) { if (other) other->incStrong(this);//这里调用的是实际对象的incStrong方法 }
void RefBase::incStrong(const void* id) const { weakref_impl* const refs = mRefs; refs->incWeak(id);//增加弱引用的计数 refs->addStrongRef(id);//debug 正式不做处理 const int32_t c = android_atomic_inc(&refs->mStrong);//原子加1 后返回+1前的值 ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs); if (c != INITIAL_STRONG_VALUE) {//判断INITIAL_STRONG_VALUE是否等于c 如果不等于那就代表已经引用了 所以返回 return; } android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); refs->mBase->onFirstRef();//第一次被引用 }上面的方法首先调用incWeak方法增加了弱引用计数然后再增加强引用计数 那我们来看看这个函数:
void RefBase::weakref_type::incWeak(const void* id) { weakref_impl* const impl = static_cast<weakref_impl*>(this); impl->addWeakRef(id);//调试用的 这里是空实现 const int32_t c = android_atomic_inc(&impl->mWeak);//原子操作加1 ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this); }可以看到当调用incStrong方法的时候会使强引用加1操作 同时弱引用也增加1 当sp退出作用域的时候会调用 析构函数:
template<typename T> sp<T>::~sp() { if (m_ptr)//如果m_ptr不为空则满足条件 m_ptr是实际对象这里满足 m_ptr->decStrong(this); }
void RefBase::decStrong(const void* id) const { weakref_impl* const refs = mRefs; refs->removeStrongRef(id); const int32_t c = android_atomic_dec(&refs->mStrong); #if PRINT_REFS LOGD("decStrong of %p from %p: cnt=%d\n", this, id, c); #endif LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs); if (c == 1) {//如果对象的引用计数为0 则满足条件 const_cast<RefBase*>(this)->onLastStrongRef(id); if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//如果对象生命周期是受弱引用的话还不能删除该对象 否则就delete 自己了 delete this; } } refs->removeWeakRef(id); refs->decWeak(id); }
void RefBase::weakref_type::decWeak(const void* id) { weakref_impl* const impl = static_cast<weakref_impl*>(this); impl->removeWeakRef(id); const int32_t c = android_atomic_dec(&impl->mWeak);//弱引用-1操作 ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this); if (c != 1) return; if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {//如果是受强引用的控制 则进入 if (impl->mStrong == INITIAL_STRONG_VALUE) {//判断是不是初始值 如果是(代表弱引用计数不是通过强引用的方式来加1)那么删掉实际对象 否则删掉管理计数的对象 也就是 weakref_impl实际对象则在Refbase中的decStrong中删除 delete impl->mBase; } else { delete impl; } } else { impl->mBase->onLastWeakRef(id); if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) { delete impl->mBase;//如果是受弱引用控制 那么就删掉实际对象 } } }
<pre name="code" class="cpp">RefBase::~RefBase() { // LOGV("Destroying RefBase %p (refs %p)\n", this, mRefs); if (mRefs->mWeak == 0) {//如果弱引用计数为0 那么删除引用计数管理 也就是weakref_impl的对象 // LOGV("Freeing refs %p of old RefBase %p\n", mRefs, this); delete mRefs; } }
template <typename T> class wp { public: typedef typename RefBase::weakref_type weakref_type; inline wp() : m_ptr(0) { }//初始化m_ptr wp(T* other); wp(const wp<T>& other); wp(const sp<T>& other); template<typename U> wp(U* other); template<typename U> wp(const sp<U>& other); template<typename U> wp(const wp<U>& other); ~wp(); // Assignment wp& operator = (T* other); wp& operator = (const wp<T>& other); wp& operator = (const sp<T>& other); template<typename U> wp& operator = (U* other); template<typename U> wp& operator = (const wp<U>& other); template<typename U> wp& operator = (const sp<U>& other); void set_object_and_refs(T* other, weakref_type* refs); // promotion to sp 升级成为强指针 sp<T> promote() const; // Reset void clear(); // Accessors inline weakref_type* get_refs() const { return m_refs; } inline T* unsafe_get() const { return m_ptr; } // Operators COMPARE(==) COMPARE(!=) COMPARE(>) COMPARE(<) COMPARE(<=) COMPARE(>=) private: template<typename Y> friend class sp; template<typename Y> friend class wp; T* m_ptr;//实际对象 weakref_type* m_refs;//操作计数类管理类从上面可以看到有两个成员变量 T 实际对象 也就是RefBase 类 里面有个管理类 weakref_impl* const mRefs ;weakref_type* m_refs这是用来干嘛的呢?
template<typename T> wp<T>::wp(T* other) : m_ptr(other)//初始化m_ptr { if (other) m_refs = other->createWeak(this);//调用对象的createWeak方法 也就是RefBase的方法 }再来看看createWeak方法:
RefBase::weakref_type* RefBase::createWeak(const void* id) const { mRefs->incWeak(id);//调用incWeak 增加对象的弱引用计数 return mRefs;//返回操作计数的管理对象 也就是weakref_type的实现类 }
template<typename T> wp<T>::~wp() { if (m_ptr) m_refs->decWeak(this);//减一操作 }弱指针是不能操作对象的因为他没有重载* ->操作费 但是他有一个方法升级成强指针来操作对象
template<typename T> sp<T> wp<T>::promote() const { return sp<T>(m_ptr, m_refs); }sp的构造函数:
template<typename T> sp<T>::sp(T* p, weakref_type* refs) : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0) { }这里首先要判断p是否为空 也就是实际对象还在不在,还要判断attemptIncStrong是否是true 是的话才能升级为强指针
bool RefBase::weakref_type::attemptIncStrong(const void* id) { incWeak(id);//增加弱引用 weakref_impl* const impl = static_cast<weakref_impl*>(this); int32_t curCount = impl->mStrong;//强引用的个数 //如果强引用的个数大于0并且还不等于初始值 那对象有强引用 while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) { if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) { break; } curCount = impl->mStrong;//增加强引用的个数 } //如果没有强引用过 或者强引用过但是已经释放了 if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) { bool allow; if (curCount == INITIAL_STRONG_VALUE) {//没有强引用过 还是初始值 //判断生命周期是不是受弱引用控制 onIncStrongAttempted()默认返回true allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK/*不受弱引用控制的话为true 代表允许升级*/ || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); } else { allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); } if (!allow) {//如果不允许的话那就得把一开始增加的弱引用减一 decWeak(id); return false; } curCount = android_atomic_inc(&impl->mStrong); // If the strong reference count has already been incremented by // someone else, the implementor of onIncStrongAttempted() is holding // an unneeded reference. So call onLastStrongRef() here to remove it. // (No, this is not pretty.) Note that we MUST NOT do this if we // are in fact acquiring the first reference. if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) { impl->mBase->onLastStrongRef(id); } } //这里代表成功升级 那么强弱都加1 impl->addWeakRef(id); impl->addStrongRef(id); #if PRINT_REFS LOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount); #endif if (curCount == INITIAL_STRONG_VALUE) { android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong); impl->mBase->onFirstRef(); } return true; }