@autoreleasePool = __AtAutoreleasePool __autoreleasePoolc++
__AtAutoreleasePool 結構體
複製代碼
AutoreleasePool 是 oc 的一種內存回收機制,正常狀況下變量在超出做用域的時候 release,可是若是將變量加入到 pool 中,那麼release 將延遲執行objective-c
AutoreleasePool 並無單獨的結構,而是由若干個 AutoreleasePoolPage 以**雙向鏈表**形式組成
1. PAGE_MAX_SIZE :4KB,虛擬內存每一個扇區的大小,內存對齊
2. 內部 thread ,page 當前所在的線程,AutoreleasePool是按線程一一對應的
3. 自己的成員變量佔用56字節,剩下的內存存儲了調用 autorelease 的變量的對象的地址,同時將一個哨兵插入page中
4. pool_boundry 哨兵標記,哨兵其實就是一個空地址,用來區分每個page 的邊界
5. 當一個Page被佔滿後,會新建一個page,並插入哨兵標記
複製代碼
單個自動釋放池的執行過程就是objc_autoreleasePoolPush()
—> [object autorelease]
—> objc_autoreleasePoolPop(void *)
markdown
具體實現以下:oop
void *objc_autoreleasePoolPush(void) {
return AutoreleasePoolPage::push();
}
void objc_autoreleasePoolPop(void *ctxt) {
AutoreleasePoolPage::pop(ctxt);
}
複製代碼
內部其實是對 AutoreleasePoolPage 的調用ui
每當自動釋放池調用 objc_autoreleasePoolPush 時,都會把邊界對象放進棧頂,而後返回邊界對象,用於釋放。spa
AutoreleasePoolPage::push();
調用👇線程
static inline void *push() {
return autoreleaseFast(POOL_BOUNDARY);
}
複製代碼
autoreleaseFast
👇指針
static inline id *autoreleaseFast(id obj) {
AutoreleasePoolPage *page = hotPage();
if (page && !page->full()) {
return page->add(obj);
} else if (page) {
return autoreleaseFullPage(obj, page);
} else {
return autoreleaseNoPage(obj);
}
}
複製代碼
👆上述方法分三種狀況選擇不一樣的代碼執行:code
- 有 hotPage 而且當前 page 不滿,調用 page->add(obj) 方法將對象添加至 AutoreleasePoolPage 的棧中
- 有 hotPage 而且當前 page 已滿,調用 autoreleaseFullPage 初始化一個新的頁,調用 page->add(obj) 方法將對象添加至 AutoreleasePoolPage 的棧中
- 無 hotPage,調用 autoreleaseNoPage 建立一個 hotPage,調用 page->add(obj) 方法將對象添加至 AutoreleasePoolPage 的棧中
最後的都會調用 page->add(obj) 將對象添加到自動釋放池中。 hotPage 能夠理解爲當前正在使用的 AutoreleasePoolPage。
複製代碼
是以棧的形式存在,而且內部對象經過進棧、出棧對應着 objc_autoreleasePoolPush 和 objc_autoreleasePoolPop
當咱們對一個對象發送一條 autorelease 消息時,其實是將這個對象地址加入到 autoreleasePoolPage 的棧頂 next 指針的指向的位置
複製代碼
iOS 在主線程註冊了兩個 observerorm
__第一個observer __
監聽了 kCFRunloopEntry, 會調用 objc_autoreleasePool_push()
第二個 observer
監聽了 kCFRunloopBeforeWaiting 會調用 objc_autoreleasePool_pop() 、objc_autoreleasePool_push()
監聽了 kCFRunloopExit 事件,會調用 objc_autoreleasePool_pop()