类在iOS系统中的加載過程
2023-12-09 00:32:09
好的,讓我們來看看 iOS 系統中,類是是如何加載的呢?這篇文章假設各位讀者都已經瞭解類、方法、物件的概念。如果還沒有,建議先閱讀完我的前幾篇文章再回來。
開始研究之前,我們先來聊聊 dyld ,這個在 macOS 中用於動態函數庫(以下簡稱「動態庫」)連接器和執行環境的工具,其用於將動態庫或是可執行文件加載到執行程序中。它通過函數 dlopen() 和 dlsym() 在執行時將函數符號和地址關聯起來。
dyld 有一個非常棒的功能,那就是它可以讓執行程序隨時決定某些函數是否可以被執行,而不是在執行程序執行前就預先決定。這就導致了一個問題,那就是可能某些時候需要執行程序在運行時才執行函數,但是不巧的是該函數在需要時卻不見了,這無疑造成了一次運行時錯誤。
dyld 的設計初衷是讓可執行程序儘可能快地啟動,這就導致在它執行時處理的部分事情很可能會出錯,但這並無大礙,這意味着我們可以讓程序盡快執行而不必為最壞的結果負責。說白了,就是 dyld 的運行是「不可信賴」的。
當動態庫第一次被加載時,它需要調用 _dyld_runtime_resolve() 函數來處理所有符号。這個函數,及其後的那些函數,將會調用 _dyld_image_lookup_for_addend() ,並通過 addends 在所有對象函數調用符號後面添加所需的常量值。
這樣做會造成函數調用緩慢,因為為了讓函數更快執行,所以才需要 addends 。
一旦函數 _dyld_image_lookup_for_addend() 完成,dyld 就會記住 CLASS Standing_DATA_$S ,如果 _OBJC_LABEL_TYPE_Mask 是 ISL_OBJC_CLASS_MASK 的話。其中 S 是一個私有函數,其執行任何符合 _OBJC_CLASS_DATA_sclassref_MASK 的數據所指向的函數。
這個函數執行 _init ,開始類的加載過程。
類的加載過程與 dyld 一樣「不可信賴」。
類加載的過程與默認類的結構變化有關。默認類結構會在執行程序運行時被緩慢填充,並且在任何函數使用它們之前,它們都無法被調用。
類的加載過程與默認類的結構變化相關。在過程中,它們會由函數緩慢地填充,並在任何函數使用它們之前都無法被調用。
類加載的過程會用到默認的類結構,那些默認的類結構在執行程序運行時會被緩慢的填滿。因此,在任何函數使用它們之前,它們都不可用。
現在我們知道類是如何加載的了,在下一篇的文章裡我們來了解一下為什麼在類中需要類別的工具。敬請期待!