美文网首页
自动释放池

自动释放池

作者: 代码歌 | 来源:发表于2022-05-13 11:13 被阅读0次

    AutoreleasePool的创建和释放

    创建

    App启动后,苹果在主线程 RunLoop 里注册了两个 Observer,其回调都是
    _wrapRunLoopWithAutoreleasePoolHandler()。

    第一个 Observer 监视的事件是 Entry(即将进入Loop),其回调内会调用
    _objc_autoreleasePoolPush() 创建自动释放池。优先级最高,保证创建释放池发生在其他所有回调之前。

    释放

    第二个 Observer 监视了两个事件: BeforeWaiting(准备进入休眠)
    时调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush()
    释放旧的池并创建新池;

    Exit(即将退出Loop) 时调用 _objc_autoreleasePoolPop() 来释放自动释放池。优先级最低,保证其释放池子发生在其他所有回调之后。

    在主线程执行的代码,通常是写在诸如事件回调、Timer回调内的。这些回调会被 RunLoop 创建好的 AutoreleasePool 环绕着,所以不会出现内存泄漏,开发者也不必显示创建 Pool 了。

    内部实现

    @ autoreleasepool {
        //AutoreleasePoolPage是C++类,调用它里面的push方法
        void *ctx = objc_autoreleasePoolPush(){
            void *objc_autoreleasePoolPush(void)
                               
            void *AutoreleasePoolPage::push(void)
         };
     
        //调用AutoreleasePoolPage中的pop函数,一次pop实际上相当于一次批量的pop操作
        objc_autoreleasePoolPop(ctx){
            void objc_autoreleasePoolPop(void *ctxt)
                                      
            AutoreleasePoolPage::pop(void *ctxt)
        };
    }
    

    在autoreleasepool中的所有对象,都会添加到自动释放池中,当进行pop之后, autoreleasepool中所有对象都会被发送一次release消息

    AutoreleasePoolPage
    • 最下面是自身占用内存,上面是用来存储AutoreleasePool中填充的对象
    • next指针指向当前栈的空位置
    • 每次进行AutoreleasePool的代码块创建的时候,相当于在栈中去插入一个【哨兵对象】
    • 进行入栈操作时,添加到next指针所指向的位置,然后next上移
    [obj autorelease]方法实现
    • 当一个对象的调用了autorelease方法,会将该对象添加到栈顶的自动释放池中
    • 当自动释放池被回收时,池子里面所有对象的使用都会做一次release操作
    AutoreleasePoolPage中Pop方法的实现

    runloop将要结束的时候调用AutoreleasePoolPage的pop()方法:

    • 哨兵对象出栈
    • 池子里面所有对象的使用都会做一次release操作
    • next指针下移

    相关文章

      网友评论

          本文标题:自动释放池

          本文链接:https://www.haomeiwen.com/subject/vpnryrtx.html