Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx

上传人:b****1 文档编号:10288520 上传时间:2023-05-24 格式:DOCX 页数:55 大小:162.87KB
下载 相关 举报
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第1页
第1页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第2页
第2页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第3页
第3页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第4页
第4页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第5页
第5页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第6页
第6页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第7页
第7页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第8页
第8页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第9页
第9页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第10页
第10页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第11页
第11页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第12页
第12页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第13页
第13页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第14页
第14页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第15页
第15页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第16页
第16页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第17页
第17页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第18页
第18页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第19页
第19页 / 共55页
Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx_第20页
第20页 / 共55页
亲,该文档总共55页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx

《Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx》由会员分享,可在线阅读,更多相关《Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx(55页珍藏版)》请在冰点文库上搜索。

Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析.docx

Android系统的智能指针轻量级指针强指针和弱指针的实现原理分析

   Android系统的运行时库层代码是用C++来编写的,用C++来写代码最容易出错的地方就是指针了,一旦使用不当,轻则造成内存泄漏,重则造成系统崩溃。

不过系统为我们提供了智能指针,避免出现上述问题,本文将系统地分析Android系统智能指针(轻量级指针、强指针和弱指针)的实现原理。

     在使用C++来编写代码的过程中,指针使用不当造成内存泄漏一般就是因为new了一个对象并且使用完之后,忘记了delete这个对象,而造成系统崩溃一般就是因为一个地方delete了这个对象之后,其它地方还在继续使原来指向这个对象的指针。

为了避免出现上述问题,一般的做法就是使用引用计数的方法,每当有一个指针指向了一个new出来的对象时,就对这个对象的引用计数增加1,每当有一个指针不再使用这个对象时,就对这个对象的引用计数减少1,每次减1之后,如果发现引用计数值为0时,那么,就要delete这个对象了,这样就避免了忘记delete对象或者这个对象被delete之后其它地方还在使用的问题了。

但是,如何实现这个对象的引用计数呢?

肯定不是由开发人员来手动地维护了,要开发人员时刻记住什么时候该对这个对象的引用计数加1,什么时候该对这个对象的引用计数减1,一来是不方便开发,二来是不可靠,一不小心哪里多加了一个1或者多减了一个1,就会造成灾难性的后果。

这时候,智能指针就粉墨登场了。

首先,智能指针是一个对象,不过这个对象代表的是另外一个真实使用的对象,当智能指针指向实际对象的时候,就是智能指针对象创建的时候,当智能指针不再指向实际对象的时候,就是智能指针对象销毁的时候,我们知道,在C++中,对象的创建和销毁时会分别自动地调用对象的构造函数和析构函数,这样,负责对真实对象的引用计数加1和减1的工作就落实到智能指针对象的构造函数和析构函数的身上了,这也是为什么称这个指针对象为智能指针的原因。

     在计算机科学领域中,提供垃圾收集(GarbageCollection)功能的系统框架,即提供对象托管功能的系统框架,例如Java应用程序框架,也是采用上述的引用计数技术方案来实现的,然而,简单的引用计数技术不能处理系统中对象间循环引用的情况。

考虑这样的一个场景,系统中有两个对象A和B,在对象A的内部引用了对象B,而在对象B的内部也引用了对象A。

当两个对象A和B都不再使用时,垃圾收集系统会发现无法回收这两个对象的所占据的内存的,因为系统一次只能收集一个对象,而无论系统决定要收回对象A还是要收回对象B时,都会发现这个对象被其它的对象所引用,因而就都回收不了,这样就造成了内存泄漏。

这样,就要采取另外的一种引用计数技术了,即对象的引用计数同时存在强引用和弱引用两种计数,例如,Apple公司提出的Cocoa框架,当父对象要引用子对象时,就对子对象使用强引用计数技术,而当子对象要引用父对象时,就对父对象使用弱引用计数技术,而当垃圾收集系统执行对象回收工作时,只要发现对象的强引用计数为0,而不管它的弱引用计数是否为0,都可以回收这个对象,但是,如果我们只对一个对象持有弱引用计数,当我们要使用这个对象时,就不直接使用了,必须要把这个弱引用升级成为强引用时,才能使用这个对象,在转换的过程中,如果对象已经不存在,那么转换就失败了,这时候就说明这个对象已经被销毁了,不能再使用了。

    了解了这些背景知识后,我们就可以进一步学习Android系统的智能指针的实现原理了。

Android系统提供了强大的智能指针技术供我们使用,这些智能指针实现方案既包括简单的引用计数技术,也包括了复杂的引用计数技术,即对象既有强引用计数,也有弱引用计数,对应地,这三种智能指针分别就称为轻量级指针(LightPointer)、强指针(StrongPointer)和弱指针(WeakPointer)。

无论是轻量级指针,还是强指针和弱指针,它们的实现框架都是一致的,即由对象本身来提供引用计数器,但是它不会去维护这个引用计数器的值,而是由智能指针来维护,就好比是对象提供素材,但是具体怎么去使用这些素材,就交给智能指针来处理了。

由于不管是什么类型的对象,它都需要提供引用计数器这个素材,在C++中,我们就可以把这个引用计数器素材定义为一个公共类,这个类只有一个成员变量,那就是引用计数成员变量,其它提供智能指针引用的对象,都必须从这个公共类继承下来,这样,这些不同的对象就天然地提供了引用计数器给智能指针使用了。

总的来说就是我们在实现智能指会的过程中,第一是要定义一个负责提供引用计数器的公共类,第二是我们要实现相应的智能指针对象类,后面我们会看到这种方案是怎么样实现的。

     接下来,我们就先介绍轻量级指针的实现原理,然后再接着介绍强指针和弱指针的实现原理。

     1.轻量级指针

     先来看一下实现引用计数的类LightRefBase,它定义在frameworks/base/include/utils/RefBase.h文件中:

viewplain

1.template   

2.class LightRefBase  

3.{  

4.public:

  

5.    inline LightRefBase() :

 mCount(0) { }  

6.    inline void incStrong(const void* id) const {  

7.        android_atomic_inc(&mCount);  

8.    }  

9.    inline void decStrong(const void* id) const {  

10.        if (android_atomic_dec(&mCount) == 1) {  

11.            delete static_cast(this);  

12.        }  

13.    }  

14.    //!

 DEBUGGING ONLY:

 Get current strong ref count.  

15.    inline int32_t getStrongCount() const {  

16.        return mCount;  

17.    }  

18.  

19.protected:

  

20.    inline ~LightRefBase() { }  

21.  

22.private:

  

23.    mutable volatile int32_t mCount;  

24.};  

     这个类很简单,它只一个成员变量mCount,这就是引用计数器了,它的初始化值为0,另外,这个类还提供两个成员函数incStrong和decStrong来维护引用计数器的值,这两个函数就是提供给智能指针来调用的了,这里要注意的是,在decStrong函数中,如果当前引用计数值为1,那么当减1后就会变成0,于是就会delete这个对象。

     前面说过,要实现自动引用计数,除了要有提供引用计数器的基类外,还需要有智能指针类。

在Android系统中,配合LightRefBase引用计数使用的智能指针类便是sp了,它也是定义在frameworks/base/include/utils/RefBase.h文件中:

viewplain

1.template   

2.class sp  

3.{  

4.public:

  

5.    typedef typename RefBase:

:

weakref_type weakref_type;  

6.  

7.    inline sp() :

 m_ptr(0) { }  

8.  

9.    sp(T* other);  

10.    sp(const sp& other);  

11.    template sp(U* other);  

12.    template sp(const sp& other);  

13.  

14.    ~sp();  

15.  

16.    // Assignment  

17.  

18.    sp& operator = (T* other);  

19.    sp& operator = (const sp& other);  

20.  

21.    template sp& operator = (const sp& other);  

22.    template sp& operator = (U* other);  

23.  

24.    //!

 Special optimization for use by ProcessState (and nobody else).  

25.    void force_set(T* other);  

26.  

27.    // Reset  

28.  

29.    void clear();  

30.  

31.    // Accessors  

32.  

33.    inline  T&      operator* () const  { return *m_ptr; }  

34.    inline  T*      operator-> () const { return m_ptr;  }  

35.    inline  T*      get() const         { return m_ptr; }  

36.  

37.    // Operators  

38.  

39.    COMPARE(==)  

40.        COMPARE(!

=)  

41.        COMPARE(>)  

42.        COMPARE(<)  

43.        COMPARE(<=)  

44.        COMPARE(>=)  

45.  

46.private:

  

47.    template friend class sp;  

48.    template friend class wp;  

49.  

50.    // Optimization for wp:

:

promote().  

51.    sp(T* p, weakref_type* refs);  

52.  

53.    T*              m_ptr;  

54.};  

     这个类的内容比较多,但是这里我们只关注它的成员变量m_ptr、构造函数和析构函数。

不难看出,成员变量m_ptr就是指向真正的对象了,它是在构造函数里面初始化的。

接下来我们就再看一下它的两个构造函数,一个是普通构造函数,一个拷贝构造函数:

viewplain

1.template  

2.sp:

:

sp(T* other)  

3.    :

 m_ptr(other)  

4.{  

5.    if (other) other->incStrong(this);  

6.}  

7.  

8.template  

9.sp:

:

sp(const sp& other)  

10.    :

 m_ptr(other.m_ptr)  

11.{  

12.    if (m_ptr) m_ptr->incStrong(this);  

13.}  

     这两个构造函数都会首先初始化成员变量m_ptr,然后再调用m_ptr的incStrong函数来增加对象的引用计数,在我们这个场景中,就是调用LightRefBase类的incStrong函数了。

     最后,看一下析构函数:

viewplain

1.template  

2.sp:

:

~sp()  

3.{  

4.    if (m_ptr) m_ptr->decStrong(this);  

5.}  

     析构函数也很简单,只是调用m_ptr的成员函数decStrong来减少对象的引用计数值,这里就是调用LightRefBase类的decStrong函数了,前面我们看到,当这个引用计数减1后变成0时,就会自动delete这个对象了。

     轻量级智能指针的实现原理大概就是这样了,比较简单,下面我们再用一个例子来说明它的用法。

     2.轻量级指针的用法

     参考在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序一文,我们在external目录下建立一个C++工程目录lightpointer,它里面有两个文件,一个lightpointer.cpp文件,另外一个是Android.mk文件。

     源文件lightpointer.cpp的内容如下:

viewplain

1.#include   

2.#include   

3.  

4.using namespace android;  

5.  

6.class LightClass :

 public LightRefBase  

7.{  

8.public:

  

9.        LightClass()  

10.        {  

11.                printf("Construct LightClass Object.");  

12.        }  

13.  

14.        virtual ~LightClass()  

15.        {  

16.                printf("Destory LightClass Object.");  

17.        }  

18.};  

19.  

20.int main(int argc, char** argv)  

21.{  

22.        LightClass* pLightClass = new LightClass();  

23.        sp lpOut = pLightClass;  

24.  

25.        printf("Light Ref Count:

 %d.\n", pLightClass->getStrongCount());  

26.  

27.        {  

28.                sp lpInner = lpOut;  

29.  

30.                printf("Light Ref Count:

 %d.\n", pLightClass->getStrongCount());  

31.        }  

32.  

33.        printf("Light Ref Count:

 %d.\n", pLightClass->getStrongCount());  

34.  

35.        return 0;  

36.}  

     我们创建一个自己的类LightClass,继承了LightRefBase模板类,这样类LightClass就具有引用计数的功能了。

在main函数里面,我们首先new一个LightClass对象,然后把这个对象赋值给智能指针lpOut,这时候通过一个printf语句来将当前对象的引用计数值打印出来,从前面的分析可以看出,如果一切正常的话,这里打印出来的引用计数值为1。

接着,我们又在两个大括号里面定义了另外一个智能指针lpInner,它通过lpOut间接地指向了前面我们所创建的对象,这时候再次将当前对象的引用计数值打印出来,从前面的分析也可以看出,如果一切正常的话,这里打印出来的引用计数值应该为2。

程序继承往下执行,当出了大括号的范围的时候,智能指针对象lpInner就被析构了,从前面的分析可以知道,智能指针在析构的时候,会减少当前对象的引用计数值,因此,最后一个printf语句打印出来的引用计数器值应该为1。

当main函数执行完毕后,智能指针lpOut也会被析构,被析构时,它会再次减少当前对象的引用计数,这时候,对象的引用计数值就为0了,于是,它就会被delete了。

     编译脚本文件Android.mk的内容如下:

viewplain

1.LOCAL_PATH :

= $(call my-dir)  

2.include $(CLEAR_VARS)  

3.LOCAL_MODULE_TAGS :

= optional  

4.LOCAL_MODULE :

= lightpointer  

5.LOCAL_SRC_FILES :

= lightpointer.cpp  

6.LOCAL_SHARED_LIBRARIES :

= \  

7.        libcutils \  

8.        libutils  

9.include $(BUILD_EXECUTABLE)  

     最后,我们参照如何单独编译Android源代码中的模块一文,使用mmm命令对工程进行编译:

viewplain

1.USER-NAME@MACHINE-NAME:

~/Android$ mmm ./external/lightpointer  

     编译之后,就可以打包了:

viewplain

1.USER-NAME@MACHINE-NAME:

~/Android$ make snod  

     最后得到可执行程序lightpointer就位于设备上的/system/bin/目录下。

启动模拟器,通过adbshell命令进入到模拟器终端,进入到/system/bin/目录,执行lightpointer可执行程序,验证程序是否按照我们设计的逻辑运行:

viewplain

1.USER-NAME@MACHINE-NAME:

~/Android$ adb shell  

2.root@android:

/ # cd system/bin/          

3.root@android:

/system/bin # ./lightpointer                                        

4.Construct LightClass Object.  

5.Light Ref Count:

 1.  

6.Light Ref Count:

 2.  

7.Light Ref Count:

 1.  

8.Destory LightClass Object.  

    这里可以看出,程序一切都是按照我们的设计来运行,这也验证了我们上面分析的轻量级智能指针的实现原理。

    3.强指针

    强指针所使用的引用计数类为RefBase,它LightRefBase类要复杂多了,所以才称后者为轻量级的引用计数基类吧。

我们先来看看RefBase类的实现,它定义在frameworks/base/include/utils/RefBase.h文件中:

viewplain

1.class RefBase  

2.{  

3.public:

  

4.    void            incStrong(const void* id) const;  

5.    void            decStrong(const void* id) const;  

6.  

7.    void            forceIncStrong(const void* id) const;  

8.  

9.    //!

 DEBUGGING ONLY:

 Get current strong ref count.  

10.    int32_t         getStrongCount() const;  

11.  

12.    class weakref_type  

13.    {  

14.    public:

  

15.        RefBase*            refBase() const;  

16.  

17.        void                incWeak(const void* id);  

18.        void                decWeak(const void* id);  

19.  

20.        bool                attemptIncStrong(const void* id);  

21.  

22.        //!

 This is only safe if you have set OBJECT_LIFETIME_FOREVER.  

23.        bool                attemptIncWeak(const void* id);  

24.  

25.        //!

 DEBUGGING ONLY:

 Get current weak ref count.  

26.        int32_t             getWeakCount() const;  

27.  

28.        //!

 DEBUGGING ONLY:

 Print references held on object.  

29.        void                printRefs() const;  

30.  

31.        //!

 DEBUGGING ONLY:

 Enable tracking for this object.  

32.        // enable -- enable/disable tracking  

33.        // retain -- when tracking is enable, if true, then we save a stack trace  

34.        //           for each reference and dereference; when retain == false, we  

35.        //           

展开阅读全文
相关搜索
资源标签

当前位置:首页 > 高等教育 > 院校资料

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2