一、前言
想要成为一名优秀的Android开发者, 我们避免不了要深入Android系统进行学习。只有搞明白了Android系统的运行机制、原理,我们才能更加得心应手的开发出性能优越的Android应用。
当然,在进行深入学习之前我们也需要具有一定的基础(例如:C++),想要深入学习Android系统的朋友们还是有必要先去学习C++的。因为在Android底层很多的核心功能都是使用C++开发出来的。
二、什么是智能指针?
使用过C++的朋友肯定都知道C++的指针,使用起来非常方便,功能强大。但是也有不足之处,就是我们必须自己去管理指针的释放,否则就会造成内存泄漏甚至程序崩溃。
那么Android在使用C++的时候, 提供了一个很方便的工具,就是智能指针。目的是帮助我们来进行对象的释放工作。其使用的基本原理就是引用计数法。
我们可以对智能指针做一些总结:
- 一种能够自动维护对象引用计数的技术
- 智能指针一是个对象,而不是一个指针
- 智能指针分为强指针、弱指针
- Android定义了一个公共基类,所有想要使用智能指针的类都要继承它
三、智能指针的公共基类
Android OS 8.0.0_r4
/system/core/include/utils/RefBase.h
class RefBase
{
public:
void incStrong(const void* id) const; // 增加强引用
void decStrong(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); // 尝试获取强引用对象,在弱引用升级强引用时会调用
};
weakref_type* createWeak(const void* id) const; // 创建弱引用
weakref_type* getWeakRefs() const;
typedef RefBase basetype;
protected使用:
RefBase();
virtual ~RefBase();// 虚析构函数,子类也要使用虚析构函数,当基类指针指向派生对象时, 如果不是虚析构函数,delete不会调用派生对象的析构函数,就有可能造成泄露
//标记生命周期的模式
enum {
OBJECT_LIFETIME_STRONG = 0x0000, // 生命周期只跟强引用有关, 当强引用为0时释放对象
OBJECT_LIFETIME_WEAK = 0x0001, // 生命周期只跟弱引用有关, 当弱引用为0时释放对象
OBJECT_LIFETIME_MASK = 0x0001
};
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; // 声明类 weakref_impl
RefBase(const RefBase& o); // 构造方法
RefBase& operator=(const RefBase& o); // 重载运算符: =
private:
weakref_impl* const mRefs; // 持有一个类weakref_impl的对象,用来管理强/弱引用计数
};
我们上面说到, 智能指针使用的是引用计数法。那么在上面好像并没有看到用来计数的变量。
其实RefBase使用的是weakref_impl来维护强引用计数和弱引用计数的。我们下面看一下weakref_impl的代码。
/system/core/libutils/RefBase.cpp
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
std::atomic<int32_t> mStrong; // 强引用计数
std::atomic<int32_t> mWeak; // 弱引用计数
RefBase* const mBase;
std::atomic<int32_t> mFlags; // 生命周期类型标记
#if !DEBUG_REFS
explicit weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE) // 强引用计数初始化的值, 不是0
, mWeak(0)
, mBase(base)
, mFlags(0)
{
}
// 非调试模式下都是空实现
void addStrongRef(const void* /*id*/) { }
void removeStrongRef(const void* /*id*/) { }
void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
void addWeakRef(const void* /*id*/) { }
void removeWeakRef(const void* /*id*/) { }
void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
void printRefs() const { }
void trackMe(bool, bool) { }
#else
...调试模式
#endif
};
上面一共看到了三个类,RefBase、weakref_type、weakref_impl。
每一个RefBase对象都包含了一个weakref_impl对象,而weakref_impl继承了weakref_type。
当我们自己的类想要使用智能指针的时候, 只需要继承RefBase就可以了。这样我们的类就拥有了weakref_impl类型的成员变量, 用来维护当前对象的引用计数。当我们把对象赋值给强指针(sp<>)或者弱指针(wp<>)的时候, 就可以不用去管理强弱指针的释放工作了, 不用的时候只需要给强弱指针赋值为NULL就可以了。
四、智能指针的强指针实现类
/system/core/include/utils/StrongPointer.h