Android中的智能指针流程

在Android的源代码中,经常会看到如:sp< xxx>、wp< xxx>这样的类型定义,这其实是Android中的智能指针。智能指针是C++中的一个概念,通过基于引用计数的方法,解决对象的自动释放的问题。
智能指针主要涉及如下几个源码文件:
/system/core/libutils/include/utils/StrongPointer.h
/system/core/libutils/include/utils/RefBase.h
/system/core/libutils/RefBase.cpp
StrongPointer.h提供sp<>强指针类型
RefBase.h 主要提供wp<>弱指针类型
一、RefBase.h 中定义了类weakref_type,声明了相关函数,

class RefBase
{
public:
            void            incStrong(const void* id) const;
            void            decStrong(const void* id) const;
    
            void            forceIncStrong(const void* id) const;

            //! DEBUGGING ONLY: Get current strong ref count.
            int32_t         getStrongCount() const;

    class weakref_type
    {
    public:
        RefBase*            refBase() const;

        void                incWeak(const void* id);
        void                decWeak(const void* id);

        // acquires a strong reference if there is already one.
        bool                attemptIncStrong(const void* id);

        // acquires a weak reference if there is already one.
        // This is not always safe. see ProcessState.cpp and BpBinder.cpp
        // for proper use.
        bool                attemptIncWeak(const void* id);

        //! DEBUGGING ONLY: Get current weak ref count.
        int32_t             getWeakCount() const;

        //! DEBUGGING ONLY: Print references held on object.
        void                printRefs() const;

        //! DEBUGGING ONLY: Enable tracking for this object.
        // enable -- enable/disable tracking
        // retain -- when tracking is enable, if true, then we save a stack trace
        //           for each reference and dereference; when retain == false, we
        //           match up references and dereferences and keep only the
        //           outstanding ones.

        void                trackMe(bool enable, bool retain);
    };
     weakref_impl* const mRefs;
 }
 template <typename T>
class wp
{
public:
    typedef typename RefBase::weakref_type weakref_type;

    inline wp() : m_ptr(0) { }
    ...
    T*              m_ptr;  //存储 new weakref_impl 对象的地址
    weakref_type*   m_refs; //m_refs 是weakref_type类型指针
 }
template<typename T>
wp<T>::wp(T* other)
    : m_ptr(other)
{
    if (other) m_refs = other->createWeak(this);
}    
template<typename T>
wp<T>::~wp()
{
    if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
wp<T>& wp<T>::operator = (T* other)
{
    weakref_type* newRefs =
        other ? other->createWeak(this) : 0;
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = other;
    m_refs = newRefs;
    return *this;
}


二、RefBase.cpp RefBase::weakref_type 中定义了RefBase.h 中声明的函数,例如:void RefBase::weakref_type::incWeak(const void* id)
同时 RefBase.cpp中 定义了类 weakref_impl ,weakref_impl 继承 类weakref_type。如下的mBase 即class RefBase 子类实例对象(对应三中的class A对象)。

class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
    std::atomic<int32_t>    mStrong; //默认强引用计数为1<<28
    std::atomic<int32_t>    mWeak;    //默认弱引用的计数为0
    RefBase* const          mBase;  //RefBase的指针
    std::atomic<int32_t>    mFlags;
	weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)//RefBase::RefBase()构造函数传递class RefBase 子类实例对象
        , mFlags(0)
        , mStrongRefs(NULL)
        , mWeakRefs(NULL)
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
        , mRetain(false)
    {
    }
	...
	void addWeakRef(const void* id) {
    addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed));
	...
	private:
    struct ref_entry
    {
        ref_entry* next;
        const void* id;
#if DEBUG_REFS_CALLSTACK_ENABLED
        CallStack stack;
#endif
        int32_t ref;
    };

    void addRef(ref_entry** refs, const void* id, int32_t mRef)
    {
        if (mTrackEnabled) {
            AutoMutex _l(mMutex);

            ref_entry* ref = new ref_entry;
            // Reference count at the time of the snapshot, but before the
            // update.  Positive value means we increment, negative--we
            // decrement the reference count.
            ref->ref = mRef;
            ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
            ref->stack.update(2);
#endif
            ref->next = *refs;
            *refs = ref;
        }
    }
	...
    }
	ref_entry* mStrongRefs;  //所有的强引用,用链表存储在这里
    ref_entry* mWeakRefs; //所有的弱引用,用链表存储在这里

}
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);
    return mRefs;
}
void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->addWeakRef(id);
    const int32_t c __unused = impl->mWeak.fetch_add(1,
            std::memory_order_relaxed);
    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id); //删除弱引用
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); //计数减1
    LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
            this);
    if (c != 1) return; //还有其他引用在用这个指针,直接返回
    atomic_thread_fence(std::memory_order_acquire);

    int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlives the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong.load(std::memory_order_relaxed)
                == INITIAL_STRONG_VALUE) {
            // Decrementing a weak count to zero when object never had a strong
            // reference.  We assume it acquired a weak reference early, e.g.
            // in the constructor, and will eventually be properly destroyed,
            // usually via incrementing and decrementing the strong count.
            // Thus we no longer do anything here.  We log this case, since it
            // seems to be extremely rare, and should not normally occur. We
            // used to deallocate mBase here, so this may now indicate a leak.
            ALOGW("RefBase: Object at %p lost last weak reference "
                    "before it had a strong reference", impl->mBase);
        } else {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
        }
    } else {
        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
        // is gone, we can destroy the object.
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;  //如果没有其他引用了,就释放当前指针
    }
}
//将weakref_impl 赋值给mRefs,同时实例化时候将this 即class RefBase 子类实例传递给	RefBase::weakref_impl 中的mBase
RefBase::RefBase()
    : mRefs(new weakref_impl(this))
{
}

RefBase::~RefBase()
{
    int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
    // Life-time of this object is extended to WEAK, in
    // which case weakref_impl doesn't out-live the object and we
    // can free it now.
    if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
        // It's possible that the weak count is not 0 if the object
        // re-acquired a weak reference in its destructor
        if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
            delete mRefs;
        }
    } else if (mRefs->mStrong.load(std::memory_order_relaxed)
            == INITIAL_STRONG_VALUE) {
        // We never acquired a strong reference on this object.
        LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
                "RefBase: Explicit destruction with non-zero weak "
                "reference count");
        // TODO: Always report if we get here. Currently MediaMetadataRetriever
        // C++ objects are inconsistently managed and sometimes get here.
        // There may be other cases, but we believe they should all be fixed.
        delete mRefs;
    }
    // For debugging purposes, clear mRefs.  Ineffective against outstanding wp's.
    const_cast<weakref_impl*&>(mRefs) = NULL;
}

三、wp<> 弱引用初始化流程
 

class A : public RefBase
{
public:
    void test();
}

以 wp<A> a = new A为例
3.1因为类A 继承了RefBase,new A的时候会调用RefBase的构造函数,此时 会调用new weakref_impl 创建弱指针实现类对象给指针变量 mRefs

RefBase::RefBase()
    : mRefs(new weakref_impl(this))


3.2从如下模板类    wp定义可知,创建wp<A> 时会调用wp<T>::wp,然后调用other->createWeak,即weakref_impl的 createWeak,最终调用
RefBase::weakref_type* RefBase::createWeak

template<typename T>
wp<T>::wp(T* other)
    : m_ptr(other)
{
    if (other) m_refs = other->createWeak(this);
}    


3.3RefBase::createWeak 方法调用 mRefs->incWeak(id) 方法,mRefs即weakref_impl。

RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);
    return mRefs;
}


3.4 mWeak 弱引用计数 默认是0,impl->mWeak.fetch_add 执行 弱引用计数 +1;impl->addWeakRef(id)

void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->addWeakRef(id);
    const int32_t c __unused = impl->mWeak.fetch_add(1,
            std::memory_order_relaxed);
    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}


3.5 weakref_impl的addWeakRef方法 中,mWeakRefs 为 ref_entry*,id为wp<A> 弱引用指针地址.

    void addWeakRef(const void* id) {
        addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed));
    }


3.6    addRef 将上面的弱引用指针地址,存储到弱引用链表存储。至此创建 wp<A> 和 new A 初始化流程结束

    void addRef(ref_entry** refs, const void* id, int32_t mRef)
    {
        if (mTrackEnabled) {
            AutoMutex _l(mMutex);

            ref_entry* ref = new ref_entry;
            // Reference count at the time of the snapshot, but before the
            // update.  Positive value means we increment, negative--we
            // decrement the reference count.
            ref->ref = mRef;
            ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
            ref->stack.update(2);
#endif
            ref->next = *refs;
            *refs = ref;
        }
    }


3.7 wp<A> a = new A ,= 运算符执行了什么操作?看一下如下运算符重载,这里的 other 对应 new A对象。
即先调用A对象的 createWeak (流程同上面2),然后调用 m_refs->decWeak 原来的 m_refs 需要decWeak,即调用
RefBase::weakref_type::decWeak

template<typename T>
wp<T>& wp<T>::operator = (T* other)
{
    weakref_type* newRefs =
        other ? other->createWeak(this) : 0;
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = other;
    m_refs = newRefs;
    return *this;
}


3.8 RefBase::weakref_type::decWeak,先删除当前的弱引用,然后引用计数减1,
如果引用计数不为1则认为还有其他引用在用这个指针,直接返回;否则认为没有其他引用 ,调用 delete impl->mBase 释放当前指针

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id); //删除弱引用
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); //获取弱引用计数给c,然后弱引用计数减1
    LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
            this);
    if (c != 1) return; //还有其他引用在用这个指针,直接返回
    atomic_thread_fence(std::memory_order_acquire);

    int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlives the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong.load(std::memory_order_relaxed)
                == INITIAL_STRONG_VALUE) {
            // Decrementing a weak count to zero when object never had a strong
            // reference.  We assume it acquired a weak reference early, e.g.
            // in the constructor, and will eventually be properly destroyed,
            // usually via incrementing and decrementing the strong count.
            // Thus we no longer do anything here.  We log this case, since it
            // seems to be extremely rare, and should not normally occur. We
            // used to deallocate mBase here, so this may now indicate a leak.
            ALOGW("RefBase: Object at %p lost last weak reference "
                    "before it had a strong reference", impl->mBase);
        } else {
            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
            delete impl;
        }
    } else {
        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
        // is gone, we can destroy the object.
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;  //如果没有其他引用了,就释放当前指针
    }
}


四、弱指针也指向一个对象,但是弱指针仅仅记录该对象的地址,不能通过弱指针来访问该对象,也就是说不能通过弱引用指针来调用对象的成员函数或访问对象的成员变量。要想访问弱指针所指向的对象,
需首先将弱指针升级为强指针(通过wp类所提供的 promote()方法)。弱指针所指向的对象是有可能在其它地方被销毁的,如果对象已经被销毁,wp的promote()方法将返回空指针,这样就能避免出现地址访问错的情况。
五、sp<> 强引用初始化流程
以 sp<A> a = new A为例,
5.1 其中 new A流程同三
5.2 从如下模板类    sp定义可知,创建sp<A>时会调用sp<T>::sp,然后调用other->incStrong,即 weakref_impl 的 incStrong ,最终调用
RefBase::incStrong,m_ptr 存储 weakref_impl 的引用

template<typename T>
sp<T>::sp(T* other)
        : m_ptr(other) {
    if (other)
        other->incStrong(this);
}


5.3 先执行 弱引用计数 +1(流程同3.4),再执行强引用计数 +1(流程参考3.4,最终是将强引用指针地址,存储到强引用链表mStrongRefs存储)。如前面 二所述 refs->mBase 对应 class RefBase 子类实例对象(对应三中的class A对象)。如果A 重写了onFirstRef方法即会调用 A中的onFirstRef方法,
即每次强引用计数+1时,回调用其对象的onFirstRef方法。

void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->incWeak(id); //弱引用计数 +1
    
    refs->addStrongRef(id);  //强引用计数 +1
    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
    ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#if PRINT_REFS
    ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    if (c != INITIAL_STRONG_VALUE)  {
        return;
    }

    int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
            std::memory_order_relaxed);
    // A decStrong() must still happen after us.
    ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
    refs->mBase->onFirstRef();
}


5.4 sp<A> a = new A,= 运算符执行了什么操作?看一下如下运算符重载,这里的 other 对应 new A对象。
即先调用A对象的 incStrong (流程同上面2),然后调用 oldPtr->decStrong 原来的 m_ptr 需要 decStrong ,即调用
RefBase::decStrong

template<typename T>
sp<T>& sp<T>::operator =(T* other) {
    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
    if (other) other->incStrong(this);
    if (oldPtr) oldPtr->decStrong(this);
    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
    m_ptr = other;
    return *this;
}


5.5 RefBase::decStrong 方法中先 移除强引用链表中的引用id,然后强引用计数-1,判断是否最后一个引用,如果是则释放该指针

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id); //移除强引用链表中的引用id
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release); //先获取当前强引用计数给c,然后强引用计数-1
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
            refs);
    if (c == 1) { //如果是最后一个了,那需要释放该指针了
        std::atomic_thread_fence(std::memory_order_acquire);
        refs->mBase->onLastStrongRef(id);
        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            delete this;
            // The destructor does not delete refs in this case.
        }
    }
    // Note that even with only strong reference operations, the thread
    // deallocating this may not be the same as the thread deallocating refs.
    // That's OK: all accesses to this happen before its deletion here,
    // and all accesses to refs happen before its deletion in the final decWeak.
    // The destructor can safely access mRefs because either it's deleting
    // mRefs itself, or it's running entirely before the final mWeak decrement.
    refs->decWeak(id); //减少弱引用链表
}


参考:
https://blog.csdn.net/qq_24451593/article/details/80112732
https://blog.csdn.net/shift_wwx/article/details/78864099

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 平台上的智能指针是一种用于管理对象生命周期的工具。在 Java 开发,Java 虚拟机(JVM)通过垃圾回收机制自动管理对象的内存释放,但在某些情况下,手动进行对象的释放和管理可能是必要的,以避免内存泄漏和资源浪费。 在 Android 开发,最常用的智能指针是弱引用(WeakReference)和软引用(SoftReference)。这两种指针都可以用来引用对象,但是它们具有不同的特性。 弱引用是一种比较短暂的引用,当对象只有弱引用指向时,即使内存不足,垃圾回收机制仍然会释放该对象。这使得弱引用特别适合处理一些临时性的对象,比如缓存的数据。在 Android ,可以使用 WeakReference 类来创建和管理弱引用。 软引用则相对于弱引用更加持久,当内存不足时,垃圾回收机制可能会释放被软引用指向的对象。软引用适合于缓存一些占用内存较大的对象,当内存不足时可以释放这些对象以避免 Out of Memory 错误。在 Android ,可以使用 SoftReference 类来创建和管理软引用。 除了弱引用和软引用,Android 还提供了其他一些智能指针类,如 PhantomReference 和 FinalizerReference,用于更灵活地管理对象的生命周期。 需要注意的是,尽管使用智能指针可以帮助更好地管理对象的生命周期,但过度使用智能指针可能会导致性能问题。因此,在使用智能指针时,需要根据具体情况慎重考虑,并在必要时手动释放对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值