Android SP 介绍
2016-04-06 11:36
435 查看
Android系统的运行时库层代码是用C++来编写的,用C++来写代码最容易出错的地方就是指针了,一旦使用不当,轻则造成内存泄漏,重则造成系统崩溃。不过系统为我们提供了智能指针,避免出现上述问题,本文将系统地分析Android系统智能指针(轻量级指针、强指针和弱指针)的实现原理。 在使用C++来编写代码的过程中,指针使用不当造成内存泄漏一般就是因为new了一个对象并且使用完之后,忘记了delete这个对象,而造成系统崩溃一般就是因为一个地方delete了这个对象之后,其它地方还在继续使原来指向这个对象的指针。为了避免出现上述问题,一般的做法就是使用引用计数的方法,每当有一个指针指向了一个new出来的对象时,就对这个对象的引用计数增加1,每当有一个指针不再使用这个对象时,就对这个对象的引用计数减少1,每次减1之后,如果发现引用计数值为0时,那么,就要delete这个对象了,这样就避免了忘记delete对象或者这个对象被delete之后其它地方还在使用的问题了。但是,如何实现这个对象的引用计数呢?肯定不是由开发人员来手动地维护了,要开发人员时刻记住什么时候该对这个对象的引用计数加1,什么时候该对这个对象的引用计数减1,一来是不方便开发,二来是不可靠,一不小心哪里多加了一个1或者多减了一个1,就会造成灾难性的后果。这时候,智能指针就粉墨登场了。首先,智能指针是一个对象,不过这个对象代表的是另外一个真实使用的对象,当智能指针指向实际对象的时候,就是智能指针对象创建的时候,当智能指针不再指向实际对象的时候,就是智能指针对象销毁的时候,我们知道,在C++中,对象的创建和销毁时会分别自动地调用对象的构造函数和析构函数,这样,负责对真实对象的引用计数加1和减1的工作就落实到智能指针对象的构造函数和析构函数的身上了,这也是为什么称这个指针对象为智能指针的原因。 解了这些背景知识后,我们就可以进一步学习Android系统的智能指针的实现原理了。Android系统提供了强大的智能指针技术供我们使用,这些智能指针实现方案既包括简单的引用计数技术,也包括了复杂的引用计数技术,即对象既有强引用计数,也有弱引用计数,对应地,这三种智能指针分别就称为轻量级指针(Light Pointer)、强指针(Strong Pointer)和弱指针(Weak Pointer)。无论是轻量级指针,还是强指针和弱指针,它们的实现框架都是一致的,即由对象本身来提供引用计数器,但是它不会去维护这个引用计数器的值,而是由智能指针来维护
轻量级指针 LightRefBase
这个类的实现比较简单, 如果要实现轻量级指针就需要配合使用 sp 合 LightRefBase继承者,通常我们需要使用轻量级指针的目标需要集成 LightRefBase 这个基类,然后放到容器 sp里面就可以实现自动维护垃圾回收,如下是这个类的简要分析:
template
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(attribute((unused)) const void* id) const {
android_atomic_inc(&mCount);
}
inline void decStrong(attribute((unused)) const void* id) const {
if (android_atomic_dec(&mCount) == 1) {
delete static_cast
if PRINT_REFS
ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
endif
if (c != INITIAL_STRONG_VALUE) { return; } //如果是第一次强引用这个目标, 就会取回调这个对象的onFirstRef,可以客制化对应的操作 android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); refs->mBase->onFirstRef();
}
注意在构造函数的时候主要做的事情总结就是增加 weak ref count, 增加 string ref count, 然后判断是否是第一次强引用这个目标,是就回调onFirstRef, 这里不设计到对象的释放,再来看sp的析构函数:
template
sp::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
这里就是直接call refbase的 decStrong, 继续分析这个函数:
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
const int32_t c = android_atomic_dec(&refs->mStrong); if (c == 1) { refs->mBase->onLastStrongRef(id); if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { delete this; } } refs->decWeak(id);
}
这里主要做的动作就是先减少强引用计数,然后这里就需要进行判断了, 如果强引用计数为0, 就可能需要delete 目标对象, 但是这个还需要进行判断,就是之前的flag, 如果这个flag设置为OBJECT_LIFETIME_STRONG, 意思就是说只要强引用计数为0, 就可以delete, 如果不是, 就可能需要判断弱引用计数,最后减少弱引用计数, refs->decWeak(id);, 再分析这个函数:
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast
相关文章推荐
- C# Pointer指针应用实例简述
- 常用汇编指令缩写(方便记忆)
- ios数据存储4种
- 再来讨论__strong 和 strong
- NSString为啥要使用Copy属性
- Rust - Reference counted and raw pointers | 引用计数和原始指针
- 认识retain copy assign strong weak 的区别
- iOS arc机制 strong weak
- ARC中的weak和strong
- strong 和 copy
- Pointer to the function
- 声明NSString属性用 Copy 与 strong 的区别
- Copy List with Random Pointer
- const pointer and array
- iOS笔记:strong、weak等详解
- [CPPHTP7 NOTES] CH8. POINTERS(1)
- [CPPHTP7 NOTES] CH8. POINTERS(2)
- [CPPHTP7 NOTES] CH8. POINTERS(3)
- [CPPHTP7 NOTES] CH8. POINTERS(4)
- [CPPHTP7 NOTES] CH8. POINTERS(5) - Maze Traversal