Android智能指针解析
1300 Words|Read in about 6 Min|本文总阅读量次
Android源码中有大量的智能指针,它们经常使用,通常一个类前会修饰sp或者wp,这种修饰即为智能指针。
Android智能指针解析
1简介
智能指针C++11
就存在,是为了媲美java
的JVM
,完全不用管对象的回收问题。
Android
的智能指针,巧妙的运用C++
的基础特性,实现对象的自动释放。
2智能指针原理
2.1作用域
2.1.1栈空间
1//demo1
2class Yangyang
3{};
4//yangyang1的作用域开始
5void demo1()
6{
7 Yangyang yangyang1;
8 //yangyang2的作用域开始
9 {
10 Yangyang yangyang2;
11 }
12 //yangyang2的作用域结束
13}
14//yangyang1的作用域结束
可以看出局部变量的作用域实际上是最近一对括号包含的范围。
2.1.2堆空间
1//demo2
2class Yangyang
3{};
4
5void demo2()
6{
7 Yangyang stackYangyang;
8 //pHeapYangyang是栈空间的变量,但是指向的是堆空间变量
9 Yangyang* pHeapYangyang = new Yangyang;
10 //指向堆空间变量的栈变量需要手动释放
11 delete pHeapYangyang;
12 //将指向堆空间的栈变量指向nullptr,防止造成野指针
13 pHeapYangyang = nullptr;
14}
3源码解析
源码里主要用到了sp
(强引用指针)和wp
(弱引用指针)的智能指针,当然还有其他类似LightRefBase
(本文不做介绍)。
Android
设计了强引用sp
和弱引用wp
,故实际对象的释放,可分为强引用控制和弱引用控制。前者是,指的是强引用数mStrong为0时,释放实际对象;后者是,则指的是弱引用数mWeak为0时,才释放实际对象。
3.1举例说明
1//demo3
2class Yangyang : public RefBase
3{
4 Yangyang() : RefBase()
5 {
6 //可以显示调用RefBase构造
7 cout << "Yangyang Constructor" << endl;
8 }
9 virtual ~Yangyang()
10 {
11 //声明virtual,可以从Yangyang派生
12 cout << "Yangyang Destructor" << endl;
13 }
14};
15
16void demo3()
17{
18 //new一个对象,pYangyang指向的是一个堆空间
19 Yangyang* pYangyang = new Yangyang();
20 //限定sp的作用域,利用sp的栈变量,spYangyang
21 {
22 sp<Yangyang> spYangyang(pYangyang);
23 //限定wp的作用域,利用wp的栈变量,wpYangyang
24 {
25 wp<Yangyang> wpYangyang(pYangyang);
26 }
27 //wpYangyang作用域结束
28 }
29 //spYangyang作用域结束
30}
结果显示
1Yangyang::-----demo3--
2Yangyang::Yangyang Constructor this(0x21127080)
3Yangyang:No refs,strong count(0x10000000),weak count(0)
4Yangyang:in sp scope Yangyang:onFirstRef,object(0x21127080)
5Yangyang::After strong ref,strong count(1), weak count(1)
6Yangyang:in wp scope Yangyang::After weak ref,strong count(1),weak count(2)
7Yangyang:out wp scope Yangyang:release weak ref,strong count(1),weak count(1)
8Yangyang::out sp scope Yangyang:onLastStrongRef,id(0x21712848)
9Yangyang:Yangyang Destructor this(0x21127080)
10Yangyang::------
3.2RefBase
RefBase
构造
1//system/core/libutils/RefBase.cpp
2//INITIAL_STRONG_VALUE 0x10000000
3//这个传入的base就是实际对象pYangyang
4//mFlags表示是否强引用,0是强引用,1是弱引用
5explicit weakref_impl(RefBase* base)
6: mStrong(INITIAL_STRONG_VALUE)
7 , mWeak(0)
8 , mBase(base)
9 , mFlags(0)
10{
11}
12
13//这里的this指的就是Yangyang的实例化对象pYangyang
14RefBase::RefBase()
15 : mRefs(new weakref_impl(this))
16{
17}
3.3sp构造
sp
构造
1//system/core/libutils/include/utils/StrongPointer.h
2inline sp() : m_ptr(nullptr) { }
3
4//这里的T就是Yangyang类,other就是pYangyang
5//这里的this,实际上是spYangyang栈变量的地址
6template<typename T>
7sp<T>::sp(T* other)
8 : m_ptr(other) {
9 if (other) {
10 check_not_on_stack(other);
11 other->incStrong(this);
12 }
13}
因为pYangyang
的Yangyang
类,继承RefBase
,所以可以找到基类RefBase
对应的函数incStrong
1//system/core/libutils/RefBase.cpp
2//这里的mRefs实际上是new weakref_impl(pYangyang)
3void RefBase::incStrong(const void* id) const
4{
5 weakref_impl* const refs = mRefs;
6 //1.弱引用增加1
7 refs->incWeak(id);
8
9 refs->addStrongRef(id);
10 //2-1.fetch_add操作之后,refs->mStrong=0x10000001,c=0x10000000
11 const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
12 ...
13 //2-2.fetch_sub操作之后,refs->mStrong=1,c=0x10000001
14 int32_t old __unused = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE, std::memory_order_relaxed);
15
16 //3调用onFirstRef,实际上调用的是pYangyang->onFirstRef
17 refs->mBase->onFirstRef();
18}
这里存在一些原子操作的函数/system/core/libcutils/include/cutils/atomic.h
函数名 | 含义 |
---|---|
android_atomic_inc |
自增函数,返回值为旧值*ptr =*ptr + 1 |
android_atomic_dec |
自减函数,返回值为旧值*ptr =*ptr - 1 |
android_atomic_add |
加函数,返回值为旧值*ptr =*ptr + increment |
android_atomic_and |
位与函数,返回值为旧值*ptr =*ptr & value |
android_atomic_or |
位或函数,返回值为旧值`*ptr =*ptr |
fetch_add |
自增函数,返回值为旧值。*this =*this + 1 |
fetch_sub |
自减函数,返回值为旧值。*this =*this - 1 |
incWeak
1//system/core/libutils/RefBase.cpp
2//这里的this指针是上面的mRefs,类型为weakref_impl* const
3void RefBase::weakref_type::incWeak(const void* id)
4{
5 weakref_impl* const impl = static_cast<weakref_impl*>(this);
6 impl->addWeakRef(id);
7 //fetch_add之后,impl->mWeak=1,c=0
8 const int32_t c __unused = impl->mWeak.fetch_add(1,
9 std::memory_order_relaxed);
10 ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
11}
因此,sp
构造完成后,mRefs
的弱引用数变为1,强引用数也变为1;第一次强引用时,回调onFirstRef()
。
3.4wp构造
弱引用构造
1//system/core/libutils/include/utils/RefBase.h
2//这里的T就是Yangyang类,other就是pYangyang
3//这里的this,实际上是wpYangyang栈变量的地址
4template<typename T>
5wp<T>::wp(T* other)
6 : m_ptr(other)
7{
8 m_refs = other ? m_refs = other->createWeak(this) : nullptr;
9}
这里的demo
不存在会创建对象失败的情况,所以这里的wp
中的m_refs
为other->createWeak(this)
,即pYangyang->createWeak(&wpYangyang)
1//system/core/libutils/RefBase.cpp
2//这里的返回值会返回当前的mRefs,是new weakref_impl(pYangyang)
3RefBase::weakref_type* RefBase::createWeak(const void* id) const
4{
5 //这里的mRefs就是new weakref_impl(pYangyang)
6 mRefs->incWeak(id);
7 return mRefs;
8}
incWeak
在3.3中已经出现过了,作用是原子操作,让mRefs->mWeak
增加1
调用incWeak
,最终的影响是弱引用数+1。当前的demo3
中,强引用数为1,弱引用数为2。
RefBase
构造的时候,mFlags
默认为0,即OBJECT_LIFETIME_STRONG
,强引用控制。设置为OBJECT LIFETIME WEAK
时,为弱引用控制。可以通过extendObjectLifetime
函数修改1//system/core/libutils/RefBase.cpp 2//如果仅仅是弱引用,需要mFlags修改成1 3void RefBase::extendObjectLifetime(int32_t mode) 4{ 5 // Must be happens-before ordered with respect to construction or any 6 // operation that could destroy the object. 7 mRefs->mFlags.fetch_or(mode, std::memory_order_relaxed); 8}
3.5wp析构
当wp
作用域结束,弱引用开始析构
1//system/core/libutils/include/utils/RefBase.h
2//这里的m_ptr是pYangyang,因为还存在所以可以操作
3//这里的m_refs是new weakref_impl(pYangyang)
4//这里的this,实际上是wpYangyang栈变量的地址
5template<typename T>
6wp<T>::~wp()
7{
8 if (m_ptr) m_refs->decWeak(this);
9}
由于m_refs
的变量是基类,m_refs
所指向的指针是派生类,这里的decWeak
不是virtual
标识,只能调用基类的decWeak
函数
1//system/core/libutils/RefBase.cpp
2void RefBase::weakref_type::decWeak(const void* id)
3{
4 //这里的static_cast就是子父类的向下转换
5 weakref_impl* const impl = static_cast<weakref_impl*>(this);
6 impl->removeWeakRef(id);
7 //fetch_sub,mRefs->mWeak=0,c=1
8 const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
9 //如果同时出现sp和wp的时候,mWeak的计数会是2,这里的c返回旧值也是2,直接返回
10 if (c != 1) return;
11 atomic_thread_fence(std::memory_order_acquire);
12
13 int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
14 //如果是强引用
15 if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
16 //如果强引用的mStrong元素时0x10000000,那么强引用错误
17 if (impl->mStrong.load(std::memory_order_relaxed)
18 == INITIAL_STRONG_VALUE) {
19 ALOGW("RefBase: Object at %p lost last weak reference "
20 "before it had a strong reference", impl->mBase);
21 } else {
22 //如果强引用mStrong是其他值,释放impl,这里实际上释放的是mRefs
23 //这里不能直接释放pYangyang,可能计数还没完全减掉
24 delete impl;
25 }
26 } else {
27 //如果只是弱引用,调用onLastWeakRef,这个impl->mBase实际上是pYangyang,即pYangyang->onLastWeakRef
28 //然后把弱引用中的impl->mBase释放,即释放的是pYangyang,会调用pYangyang的析构函数
29 impl->mBase->onLastWeakRef(id);
30 delete impl->mBase;
31 }
32}
wp析构,情况比较复杂
- 弱引用数减1
- 最后一次弱引用时,如果是强引用控制,释放
mRfs
- 若没有强引用,释放实际对象
pYangyang
demo3
来看,此时,强引用数为1,弱引用数为1,并没有任何释放
3.6sp析构
当sp
作用域结束,强引用开始析构
1//system/core/libutils/include/utils/StrongPointer.h
2//针对sp析构,m_ptr实际上是pYangyang,所以调用的是pYangyang基类RefBase的decStrong函数
3template<typename T>
4sp<T>::~sp() {
5 if (m_ptr)
6 m_ptr->decStrong(this);
7}
decStrong
1//system/core/libutils/RefBase.cpp
2//这里的mRefs
3void RefBase::decStrong(const void* id) const
4{
5 weakref_impl* const refs = mRefs;
6 refs->removeStrongRef(id);
7 //做减操作,mStrong=0,c=1
8 const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
9
10 if (c == 1) {
11 std::atomic_thread_fence(std::memory_order_acquire);
12 //如果是强引用,调用onLastStrongRef,这个impl->mBase实际上是pYangyang,即pYangyang->onLastStrongRef
13 refs->mBase->onLastStrongRef(id);
14 int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
15 //如果是强引用
16 if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
17 //这里的this指的是m_ptr,指向的是pYangyang,释放pYangyang,并调用其析构
18 delete this;
19 }
20 }
21 //做减操作,mWeak=0,c=1
22 refs->decWeak(id);
23}
3.7RefBase析构
析构完实际对象pYangyang之后,基类也同步析构
1//system/core/libutils/RefBase.cpp
2RefBase::~RefBase()
3{
4 int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
5 //如果是弱引用
6 if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
7 //弱引用计算为0,那么就把mRefs释放
8 if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
9 delete mRefs;
10 }
11 } else if (mRefs->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) {
12 //如果mStrong是0x10000000,会有RefBase相关的堆栈
13 ALOGD("RefBase: Explicit destruction, weak count = %d (in %p)", mRefs->mWeak.load(), this);
14 CallStack::logStack(LOG_TAG);
15 }
16 //清除mRefs。对未完成的wp无效
17 const_cast<weakref_impl*&>(mRefs) = nullptr;
18}
3.8总结
1)仅有sp的时候(绿色是构造,红色是析构)
2)仅有wp的时候(绿色是构造,红色是析构)
3)有sp和wp的时候(绿色是构造,红色是析构)
-
如果是demo3的场景,先出现析构wp,再出现析构sp场景
1void demo3() 2{ 3 //new一个对象,pYangyang指向的是一个堆空间 4 Yangyang* pYangyang = new Yangyang(); 5 //限定sp的作用域,利用sp的栈变量,spYangyang 6 { 7 sp<Yangyang> spYangyang(pYangyang); 8 //限定wp的作用域,利用wp的栈变量,wpYangyang 9 { 10 wp<Yangyang> wpYangyang(pYangyang); 11 } 12 //wpYangyang作用域结束 13 } 14 //spYangyang作用域结束 15}
-
如果是先析构sp,再出现析构wp的场景
1void demo4() 2{ 3 //new一个对象,pYangyang指向的是一个堆空间 4 Yangyang* pYangyang = new Yangyang(); 5 //限wp的作用域,利用wp的栈变量,wpYangyang 6 { 7 wp<Yangyang> wpYangyang(pYangyang); 8 //限定sp的作用域,利用sp的栈变量,spYangyang 9 { 10 sp<Yangyang> spYangyang(pYangyang); 11 } 12 //spYangyang作用域结束 13 } 14 //wpYangyang作用域结束 15}
4智能指针使用
源码中大量使用sp
和wp
,而且用于很广泛,也无需考虑是否足要去释放
1//frameworks/av/services/camera/libcameraservice/CameraService.cpp
2void CameraService::updateProxyDeviceState(int newState,
3 const String8& cameraId, int facing, const String16& clientName, int apiLevel) {
4 sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
5 if (proxyBinder == nullptr) return;
6 String16 id(cameraId);
7 proxyBinder->notifyCameraState(id, newState, facing, clientName, apiLevel);
8}
9
10sp<ICameraServiceProxy> CameraService::getCameraServiceProxy() {
11#ifndef __BRILLO__
12 Mutex::Autolock al(sProxyMutex);
13 if (sCameraServiceProxy == nullptr) {
14 //这里拿到ServiceManager的代理对象,即defaultServiceManager返回的是BpServiceManager
15 sp<IServiceManager> sm = defaultServiceManager();
16 //这里的checkService和getService类似,查找注册服务,前者是非阻塞,后者是阻塞的
17 sp<IBinder> binder = sm->checkService(String16("media.camera.proxy"));
18 if (binder != nullptr) {
19 //interface_cast会调用ICameraServiceProxy::asInterface(binder);
20 //asInterface又是在IInterface.h中定义的一个宏
21 //DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
22 sCameraServiceProxy = interface_cast<ICameraServiceProxy>(binder);
23 }
24 }
25#endif
26 return sCameraServiceProxy;
27}
上面以CameraService
中的ICameraServiceProxy
为例,这里的proxyBinder
是一个栈变量,但是后面的proxyBinder->notifyCameraState
,就直接将其当做一个指针使用。
这其实是正确的的,并不是乱写,一切都有迹可循
1)ICameraServiceProxy
间接继承于RefBase
,其中ICameraServiceProxy
继承IInterface
,IInterface
继承RefBase
1//path:out/soong/.intermediates/frameworks/av/camera/libcamera_client/xxx/gen/aidl/android/hardware/
2//file:ICameraServiceProxy.h
3//file:BpCameraServiceProxy.h
4//file:BnCameraServiceProxy.h
5//其中这里是ICameraServiceProxy.h
6//这里声明了一个宏,正好对应上面的ICameraServiceProxy::asInterface
7//这个宏展开
8/*
9//这个传入的obj可知道是代理客户端的IBinder
10::android::sp<ICameraServiceProxy> ICameraServiceProxy::asInterface(
11 const ::android::sp<::android::IBinder>& obj)
12{
13 ::android::sp<ICameraServiceProxy> intr;
14 if (obj != nullptr) {
15 intr = static_cast<ICameraServiceProxy*>(
16 //这里代理客户端的queryLocalInterface返回结果为nullptr
17 obj->queryLocalInterface(
18 ICameraServiceProxy::descriptor).get());
19 if (intr == nullptr) {
20 intr = new BpCameraServiceProxy(obj);
21 }
22 }
23 return intr;
24}
25*/
26DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE("CameraServiceProxy", "android.hardware.ICameraServiceProxy")
27class ICameraServiceProxy : public ::android::IInterface
28{...};
2)proxyBinder->notifyCameraState
1//system/core/libutils/include/utils/StrongPointer.h
2//proxyBinder->notifyCameraState转化为proxyBinder.operator->()->notifyCameraState,proxyBinder->()返回的是m_ptr,m_ptr指向ICameraServiceProxy的实例化对象,即ICameraServiceProxy的实例化对象的notifyCameraState调用
3inline T* operator-> () const { return m_ptr; }
关于为什么关于'->‘运算符的重载会有.operator->()的解释,具体可以点击这里
这里就涉及到C++标准对
->
运算符的语义解释因为运算符的结合律不同,解引用(*)是向右结合的,而 成员访问运算符(
.
和->
)是向左结合的。这是不同符号的结合律不同的例子,C++ 里符号相同的时候也会有用法不同导致结合律不同的例子。例如:
运算符 向左结合 向右结合 lhs op rhs / lhs op
op rhs
++
--
后缀递增/递减 前缀递增/递减 +
-
二进制加法/减法 一元加号/减号 *
二进制乘法 解引用 &
按位与 取地址 ()
函数调用 类型转换 当你重载一个左结合律的操作符时(如
+ - * / ()
等),往往这个操作符是个二元操作符,对于lhs op rhs
,就会调用lhs.operator op(rhs)
或operator op(lhs, rhs)
,我们只需要按照这个函数签名来重载操作符就行了。但是,如果这个操作符是一元操作符怎么办?这就要分情况讨论了:
1)如果这个符号有一种以上的用法(比如
++
或--
),对于lhs op
(左结合)和op rhs
(右结合),我们得想个办法区分不同的用法啊,所以就会出现用于占位的函数参数(int
):
- 对于
lhs op
调用lhs.operator op(int)
- 对于
op rhs
调用rhs.operator op()
2)如果这个符号只有一种用法(比如
->
),对于lhs op
,那就不需要用于占位的函数参数了,可以直接写成类似右结合的函数签名,即
- 对于
lhs op
调用lhs.operator op()
这是由 C++ 标准规定的,对于
ptr->mem
根据ptr
类型的不同,操作符->
的解释也不同:
- 当
ptr
的类型是内置指针类型时,等价于(*ptr).mem
- 当
ptr
的类型是类时,等价于ptr.operator->()->mem
你会发现这是一个递归的解释,对于
ptr->mem
会递归成:1(*(ptr.operator->().operator->().….operator->())).mem
操作符
->
是一元的,而操作符.
是二元的。操作符->
最终是通过操作符.
来访问成员的,而.
这个操作符是不允许重载的,只能由编译器实现。
3)服务端实现,可以发现sp
调用的客户端可以通过Binder
调用到这里,即C++
端为客户端,Java
端为服务端
1//frameworks/base/services/core/java/com/android/server/camera/CameraServiceProxy.java
2//ICameraServiceProxy.Stub()这个是匿名内部类的方式继承来最终实现
3private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
4 @Override
5 public void pingForUserUpdate() {
6 if (Binder.getCallingUid() != Process.CAMERASERVER_UID) {
7 Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " +
8 " camera service UID!");
9 return;
10 }
11 notifySwitchWithRetries(RETRY_TIMES);
12 }
13
14 @Override
15 public void notifyCameraState(String cameraId, int newCameraState, int facing,
16 String clientName, int apiLevel) {
17 if (Binder.getCallingUid() != Process.CAMERASERVER_UID) {
18 Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " +
19 " camera service UID!");
20 return;
21 }
22 String state = cameraStateToString(newCameraState);
23 String facingStr = cameraFacingToString(facing);
24 if (DEBUG) Slog.v(TAG, "Camera " + cameraId + " facing " + facingStr + " state now " +
25 state + " for client " + clientName + " API Level " + apiLevel);
26
27 updateActivityCount(cameraId, newCameraState, facing, clientName, apiLevel);
28 }
29};
补充说明:
C++
端代理调用和Java
端代理调用
Java
端代理调用通过
AIDL
的方式,系统会生成一个ICameraServiceProxy.java
文件,其中类图关系如下。调用方式
1//1)调用asInterface 2ICameraServiceProxy.Stub.asInterface(binder); 3//2)判断是否是跨进程通信,如果不是返回null,如果是实例化一个代理类对象 4mCameraServiceProxy = new ICameraServiceProxy.Stub.Proxy(binder); 5//3)根据对象调用 6mCameraServiceProxy.pingForUserUpdate(); 7//4)找到Proxy中的对应的方法,传递数据则用该方法中的transact 8ICameraServiceProxy.Stub.Proxy.pingForUserUpdate#transact; 9//5)找到Stub中的onTransact中的方法 10ICameraServiceProxy.Stub.Proxy.pingForUserUpdate#onTransact; 11//6)服务端实现ICameraServiceProxy.Stub接口,找到onTransact对应的pingForUserUpdate方法 12new ICameraServiceProxy.Stub(){...@Override public void pingForUserUpdate() {} }
C++
端代理调用通过
AIDL
的方式,系统会生成对应的四个文件,分别为ICameraServiceProxy.h
,BpCameraServiceProxy.h
,BnCameraServiceProxy.h
,ICameraServiceProxy.cpp
,具体的类图关系如下所示。调用方式
1//1)defaultServiceManager返回一个BpServiceManager 2sp<IServiceManager> sm = defaultServiceManager(); 3//2)找到对应service的IBinder,这里的IBinder是代理客户端的 4sp<IBinder> binder = sm->checkService(String16("media.camera.proxy")); 5//3)实例化一个代理类 6//interface_cast<ICameraServiceProxy>(binder)转化为ICameraServiceProxy::asInterface(binder) 7//asInterface调用到BpBinder中的queryLocalInterface,返回nullptr 8///asInterface最后返回代理客户端的BpCameraServiceProxy实例化对象 9sCameraServiceProxy = interface_cast<ICameraServiceProxy>(binder); 10//4)根据对象调用 11sCameraServiceProxy->pingForUserUpdate(); 12//5)调用到BpCameraServiceProxy.h中的函数,传递数据则用该方法中的transact 13BpCameraServiceProxy::transact; 14//6)BnCameraServiceProxy.h中的中的onTransact中的方法 15BnCameraServiceProxy::onTransact; 16//7)服务端找到onTransact中的pingForUserUpdate函数实现 17BnCameraServiceProxy::pingForUserUpdate();
关于
Binder
流程中,defaultServiceManager
返回的是BpServiceManager
,可以点击这里,本文不过多介绍。