Android的framework层都是由c++来实现的 大家都知道c++最令人头痛的莫过于内存泄漏了 ,如果是一个人开发还好 当new出来一个对象后 应该会记得delete掉 但是当多人开发的时候难免会出现这里调用了 那里忘记释放了 特别是对于Android是一个系统来说 那就更加了! 所以才有了用智能指针来处理这个问题,当没有地方引用的时候实现自动释放 避免内存泄漏或者野指针的问题。
在分析源码的过程中时常会出现sp
首先我们来看看:
template
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(this);
}
}
//获取该对象当前被引用的次数
inline int32_t getStrongCount() const {
return mCount;
}
typedef LightRefBase basetype;
protected:
inline ~LightRefBase() { }//析构
private:
mutable volatile int32_t mCount;//用来记录对象的引用次数
};
template
class sp
{
public:
inline sp() : m_ptr(0) { }//默认构造函数 初始化m_ptr为0
sp(T* other);//初始化T 这里的T代表是实际引用的对象
sp(const sp& other);//拷贝构造函数 同理
template sp(U* other);//带有返回值的构造函数
template sp(const sp& other);
~sp();
// 操作符重载
sp& operator = (T* other);
sp& operator = (const sp& other);
template sp& operator = (const sp& other);
template 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 friend class sp;
template friend class wp;//友元类
void set_pointer(T* ptr);
T* m_ptr;//这里的T就是实际引用的对象了
};
再来看看他的构造函数和拷贝构造
template
sp::sp(T* other)//这里的other实际就是LigthRefBase
: m_ptr(other)//把other赋值给m_ptr
{
if (other) other->incStrong(this);//调用LigthRefBase的incstrong
}
template
sp::sp(const sp& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) m_ptr->incStrong(this);//同上面构造函数
}
template
sp::~sp()
{
if (m_ptr) m_ptr->decStrong(this);//实际是调用LightRefBase的decStrong函数-1了 如果引用次数为0则delete该对象
}
#include
#include
using namespace android;
class MyLightClass : public LightRefBase
{
public:
MyLightClass()
{
printf("开始调用构造函数\n");
}
virtual ~MyLightClass()
{
printf("析构\n");
}
};
int main(int argc, char** argv)
{
MyLightClass* light = new MyLightClass();
sp lp = light;
printf("当前的引用次数为%d\n", light->getStrongCount());
{
sp lp2 = lp;
printf("当前的引用次数为%d\n", light->getStrongCount());
}
printf("当前的引用次数为%d\n", light->getStrongCount());
return 0;
}
现在来分析下我们写的代码 当执行到 spLOCAL_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 sa=a;
template
sp::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(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
sp::~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(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(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;//如果是受弱引用控制 那么就删掉实际对象
}
}
}
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
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline wp() : m_ptr(0) { }//初始化m_ptr
wp(T* other);
wp(const wp& other);
wp(const sp& other);
template wp(U* other);
template wp(const sp& other);
template wp(const wp& other);
~wp();
// Assignment
wp& operator = (T* other);
wp& operator = (const wp& other);
wp& operator = (const sp& other);
template wp& operator = (U* other);
template wp& operator = (const wp& other);
template wp& operator = (const sp& other);
void set_object_and_refs(T* other, weakref_type* refs);
// promotion to sp 升级成为强指针
sp 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 friend class sp;
template friend class wp;
T* m_ptr;//实际对象
weakref_type* m_refs;//操作计数类管理类
从上面可以看到有两个成员变量 T 实际对象 也就是RefBase 类 里面有个管理类 weakref_impl* const mRefs ;weakref_type* m_refs这是用来干嘛的呢?
template
wp::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
wp::~wp()
{
if (m_ptr) m_refs->decWeak(this);//减一操作
}
弱指针是不能操作对象的因为他没有重载* ->操作费 但是他有一个方法升级成强指针来操作对象
template
sp wp::promote() const
{
return sp(m_ptr, m_refs);
}
sp的构造函数:
template
sp::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(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;
}