概述
AutoreleasePool(自動釋放池)是OC中的一種內存自動回收機制,它可以延遲加入AutoreleasePool中的變量release的時機。在正常情況下,創建的變量會在超出其作用域的時候release,但是如果將變量加入AutoreleasePool,那么release將延遲執行。
@autoreleasepool實現本質
在終端中使用clang -rewrite-objc命令將OC代碼重寫成C++的實現
__AtAutoreleasePool是C++定義類
@autoreleasepool最終實現如下
AutoreleasePoolPage
自動釋放池的主要底層數據結構是:__AtAutoreleasePool 和 AutoreleasePoolPage
調用了autorelease的對象最終由AutoreleasePoolPage對象來管理
objc4源碼:NSObject.mm
每一個AutoreleasePoolPage對象占用4094字節內存,本身成員占用56字節,剩下的空間用來存放autorelease對象的地址
所有的AutoreleasePoolPage對象通過雙向鏈表的形式連接在一起
AutoreleasePoolPage管理autorelease的的對象過程
@autoreleasepool {}就對應 objc_autoreleasePoolPush(); 和 objc_autoreleasePoolPop(atautoreleasepoolobj);
objc_autoreleasePoolPush(); 內部實現:往當前hot AutoreleasePoolPage 添加 POOL_BOUNDARY,返回POOL_BOUNDARY所在的內存地址
@autoreleasepool {}代碼快如果存在對象調用了autorelease,就會將對象內存地址保存至AutoreleasePoolPage
objc4 NSObject.mm 對象- (id)autorelease方法實現
添加POOL_BOUNDARY和AutoreleasePoolPage對象后如下圖
每執行@autoreleasepool底層對應執行objc_autoreleasePoolPush(); 就會往AutoreleasePoolPage添加POOL_BOUNDARY,並返回POOL_BOUNDARY所在AutoreleasePoolPage的內存空間地址
@autoreleasepool{}大括號結束 內部創建的__AtAutoreleasePool對象銷毀,調用析構函數objc_autoreleasePoolPop(atautoreleasepoolobj);
AutoreleasePoolPage開始從后往前遍歷autorelease對象調用release方法直到objc_autoreleasePoolPop()傳入的POOL_BOUNDARY地址為止
查看AutoreleasePoolPage結構
Foundation內部存在一個全局的函數 聲明引用 然后在調用
控制台輸出
RunLoop與autorelease
iOS程序運行 在主線程中注冊了2個Observer 分別監聽RunLoop的 kCFRunLoopEntry kCFRunLoopBeforeWaiting 兩個狀態(通過打印主線程的RunLoop)
第一個Observer監聽了kCFRunLoopEntry 會調用objc_autoreleasePoolPush
第二個Observer監聽了kCFRunLoopBeforeWaiting 會調用objc_autoreleasePoolPop
MRC環境 調用的autorelease對象銷毀時機
iOS程序在程序入口main函數執行@autoreleasepool也就是atautoreleasepoolobj = objc_autoreleasePoolPush();操作 保證在程序中對象可以直接調用autorelease
上圖中person對象是有RunLoop來控制的,它可能是在某次RunLoop循環中,RunLoop休眠之前調用了release
ARC環境 方法中創建局部對象銷毀時機
上圖中person對象取決於ARC是對person添加釋放代碼是生成autorelease還是在方法結束之前生成release,經過調試驗證ARC在方法結束前插入一句
[person release],所以ARC下局部對象是在方法結束釋放。