Runtime 01 - isa

Runtime 01 - isa

Runtime 又叫運(yùn)行時,是一套 C 語言的 API辣往,Objective-C 是一門動態(tài)編程語言愤兵,其動態(tài)性是由 Runtime 來支撐和實現(xiàn)的,Runtime 源碼由 C/C++/匯編語言編寫排吴。

在使用 Objective-C 編碼的過程中,可以給任意一個對象發(fā)送消息懦鼠,在編譯階段只是確定了要向接受者發(fā)送這條消息钻哩,而接收者如果響應(yīng)和處理消息屹堰,在運(yùn)行時階段來決定。

平時編寫的 Objective-C 代碼街氢,都會由編譯器轉(zhuǎn)換成運(yùn)行時代碼扯键,很多操作會推遲到運(yùn)行時再進(jìn)行。

當(dāng)我們導(dǎo)入 objc/runtime.h 和 objc/message.h 后珊肃,會發(fā)現(xiàn)代碼提示不全荣刑,原因是從 Xcode5 開始,官方不建議我們手動調(diào)用 Runtime API伦乔±骺鳎可以通過修改 Build Settings 中的一個配置項來解決。



默認(rèn)值為 YES烈和,修改為 NO 即可爱只。

Runtime 的具體應(yīng)用

  • 使用關(guān)聯(lián)對象(AssociatedObject)為 Category 添加屬性。
  • 遍歷 Class 的所有成員變量(修改 UITextField 的占位文本顏色招刹、字典轉(zhuǎn)模型恬试、自動歸檔解檔等)。
  • 交換方法實現(xiàn)(交換系統(tǒng)的方法)疯暑。
  • 利用消息轉(zhuǎn)發(fā)機(jī)制解決方法找不到的異常問題训柴。
  • ...

isa

  • 要了解 Runtime,首先要了解它底層的一些常用數(shù)據(jù)結(jié)構(gòu)妇拯,比如 isa 指針幻馁。
  • 在 arm64 架構(gòu)之前,isa 就是一個普通的指針乖阵,存儲著 Class 對象宣赔、Meta-Class 對象的內(nèi)存地址。
  • 從 arm64 架構(gòu)開始瞪浸,對 isa 進(jìn)行了優(yōu)化儒将,變成了一個共用體(union),還使用位域來存儲更多信息对蒲。

isa_t 源碼(對 objc_class 的解讀參考這里Objective-C 對象的本質(zhì) 01 - 底層實現(xiàn)):

typedef unsigned long uintptr_t;

union isa_t {
    isa_t() { }
    isa_t(uintprt_t value) : bits(value) { }
    
    Class cls;
    uintptr_t bits;
    
    // 通過掩碼的方式獲取 shiftcls 和 magic 的值钩蚊。
    # define ISA_MASK        0x0000000ffffffff8ULL
    # define ISA_MAGIC_MASK  0x000003f000000001ULL
    # define ISA_MAGIC_VALUE 0x000001a000000001ULL
    
    struct {
        uintptr_t nonpointer        : 1;
        uintptr_t has_assoc         : 1;
        uintptr_t has_cxx_dtor      : 1;
        uintptr_t shiftcls          : 33; // MACH_VM_MAX_ADDRESS 0x1000000000
        uintptr_t magic             : 6;
        uintptr_t weakly_referenced : 1;
        uintptr_t deallocating      : 1;
        uintptr_t has_sidetable_rc  : 1;
        uintptr_t extra_rc          : 19;
        # define RC_ONE   (1ULL<<45)
        # define RC_HALF  (1ULL<<18)
    };
};

isa 位域

  • nonpointer:
    • 0:代表普通指針,存儲著 Class 對象蹈矮、Meta-Class 對象的內(nèi)存地址砰逻。
    • 1:代表開啟 isa 指針優(yōu)化,使用位域存儲更多的信息泛鸟。
  • has_assoc:
    • 是否有設(shè)置過關(guān)聯(lián)對象蝠咆,如果沒有,釋放時會更快。
  • has_cxx_dtor:
    • 是否有 C++ 的析構(gòu)函數(shù)(.cxx_destruct)刚操,如果沒有闸翅,釋放時會更快。
  • shiftcls:
    • 存儲著 Class 對象菊霜、Meta-Class 對象的內(nèi)存地址坚冀,arm64 架構(gòu)中有 33 位可以存儲地址。
    • 根據(jù) ISA_MASK 可以得知鉴逞,Class 對象记某、Meta-Class 對象的內(nèi)存地址值后三位(二進(jìn)制位)永遠(yuǎn)為0。
  • magic:
    • 用戶判斷對象是否初始化完成构捡,在 arm64 中 0x16 是調(diào)試器判斷當(dāng)前對象是初始化完成的還是沒有初始化的空間液南。
  • weakly_referenced:
    • 是否有被弱引用指向過,如果沒有叭喜,釋放時會更快贺拣。
  • deallocating:
    • 對象是否正在釋放內(nèi)存。
  • has_sidetable_rc:
    • 用于判斷對象的引用計數(shù)是否過大捂蕴,如果 extra_rc 位域無法容納引用計數(shù)譬涡,會存儲到 SideTable 的屬性中。
  • extra_rc:
    • 存放對象的引用計數(shù)值減一后的結(jié)果啥辨,對象的引用計數(shù)超過 1涡匀,會存儲到這里。

從 objc_destructInstance 函數(shù)中溉知,可以看到對象設(shè)置過關(guān)聯(lián)對象或有 C++ 析構(gòu)函數(shù)陨瘩,會進(jìn)行對應(yīng)的釋放操作。

/***********************************************************************
* objc_destructInstance
* Destroys an instance without freeing memory. 
* Calls C++ destructors.
* Calls ARC ivar cleanup.
* Removes associative references.
* Returns `obj`. Does nothing if `obj` is nil.
**********************************************************************/
void *objc_destructInstance(id obj) 
{
    if (obj) {
        // Read all of the flags at once for performance.
        bool cxx = obj->hasCxxDtor();
        bool assoc = obj->hasAssociatedObjects();

        // This order is important.
        if (cxx) object_cxxDestruct(obj);
        if (assoc) _object_remove_assocations(obj);
        obj->clearDeallocating();
    }

    return obj;
}

參考資料

神經(jīng)病院Objective-C Runtime入院第一天——isa和Class

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末级乍,一起剝皮案震驚了整個濱河市舌劳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玫荣,老刑警劉巖甚淡,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異捅厂,居然都是意外死亡贯卦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門焙贷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撵割,“玉大人,你說我怎么就攤上這事辙芍》缺颍” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長庶灿。 經(jīng)常有香客問我注簿,道長,這世上最難降的妖魔是什么跳仿? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮捐晶,結(jié)果婚禮上菲语,老公的妹妹穿的比我還像新娘。我一直安慰自己惑灵,他們只是感情好山上,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布省有。 她就那樣靜靜地躺著骗爆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪枉昏。 梳的紋絲不亂的頭發(fā)上干花,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天妄帘,我揣著相機(jī)與錄音,去河邊找鬼池凄。 笑死抡驼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肿仑。 我是一名探鬼主播致盟,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼尤慰!你這毒婦竟也來了馏锡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤伟端,失蹤者是張志新(化名)和其女友劉穎杯道,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荔泳,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡蕉饼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了玛歌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昧港。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖支子,靈堂內(nèi)的尸體忽然破棺而出创肥,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布叹侄,位于F島的核電站巩搏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏趾代。R本人自食惡果不足惜贯底,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撒强。 院中可真熱鬧禽捆,春花似錦、人聲如沸飘哨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芽隆。三九已至浊服,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胚吁,已是汗流浹背牙躺。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留囤采,地道東北人述呐。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像蕉毯,于是被迫代替她去往敵國和親乓搬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353