前言

之前有写过一篇关于AutoreleasePool的理解的总结,总觉的不够深入,所以重起一篇。本篇从阅读官方文档和autorelasepool的源码入手来记录。

Autorelease Pool

什么是autorelease pool

从官方文档中的解释,autorelease pool存储着一些对象,当向pool发送drain消息时会向池中全部对象发送release消息。

autorelease pool的创建和池内对象的释放时机

应用程序在每次事件循环(event loop)的开始,自动在主线程上创建一个自动释放池,并在每次事件循环(event loop)结束时向池内对象发送release消息进行释放。手动创建的autorelease pool中的对象在block外被释放掉。

autorelease pool 与 thread

当你通过NSThread另外开辟的子线程时,你需要自己创建一个autorelease pool。子线程默认是没有自动释放池的。但是使用GCD开辟的线程会自动创建pool。

autorelease pool的结构

我们都知道在iOS开发中,main函数作为程序的入口,包含了一个@autoreleasepool,我们通过clang重新编译一下会发现main函数的实现变成了下图的样子

@autoreleasepool被转成了一个__AtAutoreleasePool。__AtAutoreleasePool是一个结构体

结构体的构造函数中会调用objc_autoreleasePoolPush(),析构函数中会调用objc_autoreleasePoolPop(void *)

这俩个方法可以再NSObject.mm的源码中找到实现。

方法实现中出现了一个新的类AutoreleasePoolPage,提取出来的大致定义是这样的

magic 用来校验 AutoreleasePoolPage 的结构是否完整;

next 指向最新添加的 autoreleased 对象的下一个位置,初始化时指向 begin() ;

thread 指向当前线程;

parent 指向父结点,第一个结点的 parent 值为 nil ;

child 指向子结点,最后一个结点的 child 值为 nil ;

depth 代表深度,从 0 开始,往后递增 1;

hiwat 代表 high water mark

当next指向begin时代表该page为空,当next指向end时代表page已满。

autorelease pool就是由这些page组成的双向链表结构且每一个page的可用空间是固定的4096个字节

objc_autoreleasePoolPush

上面说了_AtAutoreleasePool在初始化的时候会调用objc_autoreleasePoolPush,我们来看下这个方法的实现,整理后差不多是这样

调用autoreleaseFast并传入POOL_BOUNDARY。

POOL_BOUNDARY(哨兵)

POOL_BOUNDARY实际上就是nil,当调用objc_autoreleasePoolPush方法的时候,POOL_BOUNDARY被最先加入到pool中并置于栈顶。同时哨兵的地址也作为objc_autoreleasePoolPop方法的入参来寻找需要进行pop操作的page。

autoreleaseFast (hotPage:当前正在使用的page)

大体的逻辑是这样

  1. 通过hotPage()方法获取hotPage
  2. 当hotPage存在并且空间未满时将传入的obj添加到page中
  3. 如果hotPage满了,就另外新建一个page并将obj添加到里面
  4. 如果hotPage不存在,就创建一个hotPage并将obj添加到里面

hotPage

通过tls(Thread Local Storage)获取hotPage

page->add()

autoreleaseFullPage

autoreleaseNoPage

创建一个parent为nil的page并添加一个哨兵,之后再将传入的obj添加到page中。

那么一个obj什么时候被添加到autorelease pool中的呢。只有当一个对象被调用了autorelease方法的时候,该对象才会被加入到autorelease pool中。在MRC的环境下,开发者需要进行手动调用,而ARC的环境下,非alloc/copy/mutablecopy创建的对象都是autorelease对象,若想将通过alloc/copy/mutablecopy创建的对象变为autorelease对象只需要创建时在前面添加__autorelease关键字。

autorelease

rootAutorelease

rootAutorelease2

确保非TaggedPointer后调用page的autorelease方法,之后进入autoreleaseFast流程成功将对象加入到autorelease pool中。

objc_autoreleasePoolPop操作

大体上的执行顺序包括pop() ==> releaseUntil(stop) ==> page->child->kill()

也就是根据传入的stop不断释放对象直到stop的地址,之后开始kill掉childPage。

而objc_autoreleasePoolPop调用时机就是当[NSAutoreleasePool release]的时候。

转载于:https://www.cnblogs.com/kaisi/p/10119095.html

Autorelease Pool相关推荐

  1. 关于autorelease pool一个较好的理解

    2019独角兽企业重金招聘Python工程师标准>>> 如果你能够真正的理解autorelease,那么你才是理解了Objective c的内存管理.Autorelease实际上只是 ...

  2. Objective-C Autorelease Pool 的实现原理[转]

    http://blog.leichunfeng.com/blog/2015/05/31/objective-c-autorelease-pool-implementation-principle/ 内 ...

  3. NSRunLoop中Autorelease pool 管理

    http://segmentfault.com/q/1010000000123664 iOS的运行时是由一个一个runloop组成的,每个runloop都会执行下图的一些步骤: 可以看到,每个runl ...

  4. RunLoop总结:RunLoop 与GCD 、Autorelease Pool之间的关系

    如果在面试中问到RunLoop相关的知识,很有可能也会问到RunLoop与GCD.Autorelease Pool有没有关系,哪些地方用到了GCD.Autorelease Pool等. So,本文就总 ...

  5. gitk产生的错误 autorelease pool page 0x7f8d45239000 corrupted

    今天使用gitk查看提交变动时,发现报错了.不知道是从另一台电脑上迁移的有问题还是其他导致的,头疼啊. 当前系统环境mac os Catalina(10.15.7) 报错信息如下: objc[1552 ...

  6. (ios实战):retain,copy,assign及autorelease ,strong,weak

    一,retain, copy, assign区别 1. 假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又把a赋值给(assign)了b.此时a ...

  7. autorelease使用注意事项

    1.autorelease是什么? autorelease是一种支持引用计数的内存管理方式 它可以暂时的保存某个对象(object),然后在内存池自己的排干(drain)的时候对其中的每个对象发送re ...

  8. (转)Objective-C Autorelease Pools(自动释放池)详解

    本篇将给您介绍"Autorelease Pools"(自动释放池)在应用中的使用技巧. 1,Autorelease Pools概要 一个"Autorelease Pool ...

  9. (转)黑幕背后的Autorelease

    转载地址:http://blog.sunnyxx.com/2014/10/15/behind-autorelease/ 我是前言 Autorelease机制是iOS开发者管理对象内存的好伙伴,MRC中 ...

最新文章

  1. 因为BitMap,白白搭进去8台服务器...
  2. JaveWeb 公司项目(4)----- Easyui的表单验证
  3. python吃内存还是cpu_Python2 得到 CPU 和内存信息要怎么实现呢?
  4. OpenGL无边界的纹理实例
  5. python 示例_带有示例的Python date isocalendar()方法
  6. 使用Quartz来实现动态定时任务
  7. 算法:求数的幂次方powx-n
  8. Android USB Camera(2) : UVC协议分析
  9. JAVA课设日记本,java课程设计(日记本)
  10. fft 重叠加法_信号分析之:FFT计算中的“重叠”处理 (Overlap Processing)
  11. Java机器学习库(Java ML)(二、聚类)
  12. 球面绘制六边形——二维平面坐标转成三维球面坐标
  13. 飞秋怎么搜索指定ip好友_飞秋怎么加好友
  14. 免疫治疗之非小细胞肺癌 | MedChemExpress
  15. IOS微信浏览器input输入账号键盘闪烁
  16. 布局篇-WrapPanel布局
  17. 使用python实现图像对比度增强
  18. docker启动容器发生Error response from daemon故障
  19. 黑马程序员——OC基础---核心语法(id,构造方法,Category,description,SEL)
  20. 全志H616方案香橙派Zero2开发板Linux系统设置静态 IP 地址的方法

热门文章

  1. 【狂神MySQL笔记】初识Mysql
  2. 【java笔记】线程(4):匿名内部类创建线程
  3. 【深度优先搜索】计蒜客:正方形
  4. 【最短路问题】leetcode743. 网络延迟时间
  5. 8运行不了_民航局暂停运行737max8,分析可能因为“它”导致飞机俯冲坠落
  6. 支持Linux系统恢复工具,12款Linux系统恢复工具
  7. python rpy2时间序列_当从多线程使用rpy2调用r函数时,模型作为r函数的参数
  8. Helm 3 完整教程(十七):Helm 流控制结构(1)if / else 语句
  9. macOS下JetBrains配置修改错误导致无法启动解决方案
  10. SpringMVC中RequestMethod同时支持POST和GET访问