Person
类继承自NSObject
, 在main
函数中代码以下cd
到main.m
所在文件夹, 并执行下面的命令xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m
复制代码
main.cpp
文件拖到项目中并打开, 能够找到main.m
文件在底层的代码__AtAutoreleasePool
结构体main
函数中的代码能够模拟为下图所示@autoreleasepool
, 能够从objc_autoreleasePoolPush
函数和objc_autoreleasePoolPop
函数入手objc_autoreleasePoolPush
函数的底层实现objc_autoreleasePoolPop
函数的底层实现objc_autoreleasePoolPush
和objc_autoreleasePoolPop
, 都是用了AutoreleasePoolPage
AutoreleasePoolPage
中的主要成员变量自动释放池的主要底层数据结构是:__AtAutoreleasePool、AutoreleasePoolPage
调用了autorelease的对象最终都是经过AutoreleasePoolPage对象来管理的ios
AutoreleasePoolPage
对象占用4096字节内存,除了用来存放它内部的成员变量,剩下的空间用来存放autorelease
对象的地址AutoreleasePoolPage
中除了一开始的56
个字节用来存储成员变量, 其余的全部内存空间都是用来存储被autorelease
对象的地址begin
和end
两个函数的实现以下begin = AutoreleasePoolPage地址 + AutoreleasePoolPage的大小
end = AutoreleasePoolPage地址 + SIZE(4096)缓存
AutoreleasePoolPage
不够存储autorelease
对象地址时, 就会在建立一个AutoreleasePoolPage
AutoreleasePoolPage
对象经过双向链表的形式链接在一块儿调用push
方法会将一个POOL_BOUNDARY
入栈,而且返回其存放的内存地址bash
调用pop
方法时传入一个POOL_BOUNDARY
的内存地址,会从最后一个入栈的对象开始发送release
消息,直到遇到这个POOL_BOUNDARY
数据结构
id *next
指向了下一个能存放autorelease
对象地址的区域iphone
能够经过如下私有函数来查看自动释放池的状况 extern void _objc_autoreleasePoolPrint(void);
函数
使用_objc_autoreleasePoolPrint
函数, 查看一个空的autoreleasepool
oop
autorelease
对象page
中有两个缓存, 其中一个POOL
就是POOL_BOUNDARY
, 第二个就是加入的Person
对象page
中存储三个内容, 一个POOL_BOUNDARY
, 两个Person
对象@autoreleasepool
, 代码以下page
中存储了两个POOL_BOUNDARY
@autoreleasepool
, 代码以下page
中存储了三个POOL_BOUNDARY
@autoreleasepool
存放1000
个Person
的autorelease
对象page
存储空间用满了, 会再次建立一个page
Runloop
中注册了2个Observer
Observer
监听了kCFRunLoopEntry
事件,会调用objc_autoreleasePoolPush()
Observer
kCFRunLoopBeforeWaiting
事件,会调用objc_autoreleasePoolPop()、objc_autoreleasePoolPush()
kCFRunLoopBeforeExit
事件,会调用objc_autoreleasePoolPop()