autoreleasepool 原理解析

2024-01-31 06:58

本文主要是介绍autoreleasepool 原理解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

虽然在ARC时代我们可以完全不知道Autorelease就能管理好内存,但在了解Objective-C内存管理还是十分重要的,在阅读了书籍和一些干货并动手验证之后,决定总结autoreleasePool的实现。


什么是autorelease

autoreleasePool如何实现需要先知道什么是autorelease

autorelease类似于C语言中Automatic variable自动变量,程序执行时,若某自动变量超出其作用域,该自动变量将被自动废弃。

autorelease何时释放

面试时提问Objective-C内存管理基本都会问到autorelease何时释放,在没有使用@autoreleasepool的情况,autorelease对象是在当前的runloop迭代结束时释放。

每个runloop中都会创建一个 autoreleasepool 并在runloop迭代结束进行释放。

如果是手动创建autoreleasepool,自己创建Pool并释放:

Apple文档中提到:

不管是MRC还是ARC最好使用@autoreleasepool blocks。

@autoreleasepool

上面提到的使用@autoreleasepool来手动创建并释放autorelease
@autoreleasepool 使用clang编译之后

@autoreleasepool被转转换成__AtAutoreleasePool 结构体类型

可以看到 __AtAutoreleasePool() 构造函数调用objc_autoreleasePoolPush(),~__AtAutoreleasePool() 析构函数调用 objc_autoreleasePoolPop()

在 MRC 中我们使用 NSAutoreleasePool 来创建AutoreleasePool,那么相应的实现如下:

objc_autoreleasePoolPush 和 objc_autoreleasePoolPop是什么呢?

objc_autoreleasePoolPush 和 objc_autoreleasePoolPop实现需要从runtime源代码看到,文中的代码的是最新的objc4-706.tar.gz

在 NSObject.mm 文件中:

113672149-c7f5b4dc5a9b6dd9

NSObject.mm

实际上是调用AutoreleasePoolPagepushpop两个类方法

AutoreleasePoolPage

首先来看一下AutoreleasePoolPage这个类

123672149-a8e6a554b3f6d107

AutoreleasePoolPage
  • magic 检查校验完整性的变量
  • next 指向新加入的autorelease对象下一个位置如下图:
133672149-2ab66fa726b31ac6

next
  • thread page当前所在的线程
  • parent 父节点 指向前一个page
  • child 子节点 指向下一个page
  • depth 链表的深度,节点个数
  • hiwat high water mark 数据容纳的一个上限
  • EMPTY_POOL_PLACEHOLDER 空池占位
  • POOL_BOUNDARY 是一个边界对象 nil,之前的源代码变量名是 POOL_SENTINEL哨兵对象,用来区别每个page即每个 AutoreleasePoolPage 边界
  • PAGE_MAX_SIZE 定义的大小在下图可以看到:
143672149-dab24ef25b8c7574

PAGE_MAX_SIZE
  • PAGE_MAX_SIZE = 4096, 为什么是4096呢?其实就是虚拟内存每个扇区4096个字节,4K对齐的说法。
  • COUNT 一个page里对象数

在自动释放池中每一个AutoreleasePoolPage

都是以双链表的形式连接起来的:

153672149-7ea8e16cedb69d1b

Pool

parent指向前一个page , child指向下一个page

push

163672149-25e788aede2fe5d5

push

每当自动释放池调用objc_autoreleasePoolPush时都会把边界对象放进栈顶,然后返回边界对象,用于释放。

atautoreleasepoolobj 就是返回的边界对象

push就是压栈的操作,先加入边界对象然后添加A对象在边界对象之后,下一个B对象压入A对象之后,就像羽毛球筒放羽毛球一样

pop

173672149-8c3a6a9f0f117355

pop

自动释放池释放是传入 push 返回的边界对象,

然后将边界对象指向的这一页 AutoreleasePoolPage 内的对象释放

@End

总结:

  1. 自动释放池是一个个 AutoreleasePoolPage 组成的一个page是4096字节大小,每个 AutoreleasePoolPage 以双向链表连接起来形成一个自动释放池
  2. pop 时是传入边界对象,然后对page 中的对象发送release 的消息

文章有什么理解不是很到位的希望指出

参考资料

  • 《Objective-C高级编程:iOS与OS X多线程和内存管理》
  • 自动释放池的前世今生 —- 深入解析 autoreleasepool
  • NSAutoreleasePool
  • 黑幕背后的Autorelease

这篇关于autoreleasepool 原理解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/662917

相关文章

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

鸿蒙中@State的原理使用详解(HarmonyOS 5)

《鸿蒙中@State的原理使用详解(HarmonyOS5)》@State是HarmonyOSArkTS框架中用于管理组件状态的核心装饰器,其核心作用是实现数据驱动UI的响应式编程模式,本文给大家介绍... 目录一、@State在鸿蒙中是做什么的?二、@Spythontate的基本原理1. 依赖关系的收集2.

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

关于WebSocket协议状态码解析

《关于WebSocket协议状态码解析》:本文主要介绍关于WebSocket协议状态码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录WebSocket协议状态码解析1. 引言2. WebSocket协议状态码概述3. WebSocket协议状态码详解3

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、