Android 自己的智能指针
在 Android 系统中,强指针模板类(sp<T>) 是一种基于引用计数的智能指针实现,专门用于管理对象的生命周期。它被广泛用于 Android Framework 的底层(Native 层/C++ 代码),尤其是与 Binder 通信相关的模块。
1. sp<T> 的定义与作用
- 模板类:
sp<T>是一个模板类(定义在<utils/StrongPointer.h>中),通过泛型支持任意类型的对象。 - 强引用语义:通过引用计数(Reference Counting)跟踪对象的使用情况,确保对象在不再被任何指针引用时自动释放内存。
- 设计目标:解决 Android 系统中 Native 层对象生命周期管理的复杂性,避免内存泄漏和野指针问题。
2. 强指针服务对象
引用计数机制
- 每个被
sp<T>管理的对象必须继承自RefBase类(定义在<utils/RefBase.h>)。 RefBase提供了两个引用计数器:- 强引用计数(Strong Count):由
sp<T>管理,归零时对象被销毁。 - 弱引用计数(Weak Count):由
wp<T>(弱指针)管理,归零时对象的控制块被释放(但对象内存可能已被强引用释放)。
- 强引用计数(Strong Count):由
sp<T> 的实现原理
-
构造
sp<T>
当sp<T>指向一个对象时,会调用RefBase::incStrong()增加强引用计数。template<typename T> sp<T>::sp(T* other) : m_ptr(other) {if (other) other->incStrong(this); } -
析构
sp<T>
当sp<T>超出作用域或被重置时,调用RefBase::decStrong()减少强引用计数。若计数归零,销毁对象。template<typename T> sp<T>::~sp() {if (m_ptr) m_ptr->decStrong(this); } -
赋值与拷贝
拷贝或赋值操作会调整引用计数,确保新旧指针的正确管理:sp<ProcessState> p1 = new ProcessState(); 或者 sp<ProcessState> p1(new ProcessState()); // 强引用计数=1 sp<ProcessState> p2 = p1; // 强引用计数=2
3. sp<T> 与 RefBase 的关系
-
对象必须继承
RefBase
只有继承自RefBase的类才能被sp<T>管理。例如:class ProcessState : public virtual RefBase {// ... }; -
RefBase的关键方法incStrong():增加强引用计数。decStrong():减少强引用计数,可能触发对象销毁。onFirstRef():当强引用计数从 0 变为 1 时调用(首次被引用)。onLastStrongRef():当强引用计数归零时调用(即将销毁)。
4. 使用场景示例
示例 1:Binder 代理对象的生命周期管理
在 Binder 通信中,客户端通过 sp<IBinder> 持有服务端的代理对象:
// 获取 ServiceManager 的代理
sp<IServiceManager> sm = defaultServiceManager();// 获取 BatteryService 的 Binder 代理对象
sp<IBinder> binder = sm->getService(String16("battery"));// 将 IBinder 转换为具体的服务接口
sp<IBatteryService> batteryService = interface_cast<IBatteryService>(binder);
sp<T>确保代理对象在不再被使用时自动释放。
示例 2:单例模式的资源管理
在 ProcessState 单例中,使用 sp<T> 确保全局唯一实例的正确释放:
sp<ProcessState> ProcessState::self() {static sp<ProcessState> gProcess(new ProcessState);return gProcess;
}
5. sp<T> vs C++ 标准智能指针
| 特性 | sp<T> (Android) | std::shared_ptr<T> (C++11) |
|---|---|---|
| 依赖对象基类 | 必须继承 RefBase | 无要求(通过 std::enable_shared_from_this 可选) |
| 性能优化 | 为嵌入式系统优化,轻量级 | 通用实现,可能略重 |
| 线程安全 | 引用计数操作是原子的(线程安全) | 默认线程安全(依赖实现) |
| 弱指针支持 | 通过 wp<T> 实现 | 通过 std::weak_ptr<T> 实现 |
| 内存开销 | 每个对象附带 RefBase 的控制块 | 每个 shared_ptr 有单独的控制块 |
6. 注意事项
-
循环引用
sp<T>无法自动处理循环引用(如对象 A 持有sp<B>,对象 B 持有sp<A>),需结合wp<T>(弱指针)打破循环。 -
继承
RefBase
若类未继承RefBase,使用sp<T>会导致编译错误。 -
跨模块传递
确保对象的所有权通过sp<T>明确传递,避免裸指针(T*)脱离智能指针管理。 -
线程安全
虽然sp<T>的引用计数操作是原子的,但对象本身的线程安全性需开发者自行保证。
