iOS底層原理--Runtime isa

runtime簡(jiǎn)介

運(yùn)行時(shí)(Runtime)是指將數(shù)據(jù)類型的確定由編譯時(shí)推遲到了運(yùn)行時(shí),Runtime是一套比較底層的純C語(yǔ)言API, 屬于1個(gè)C語(yǔ)言庫(kù), 包含了很多底層的C語(yǔ)言API,平時(shí)編寫(xiě)的OC代碼,在程序運(yùn)行過(guò)程中,其實(shí)最終會(huì)轉(zhuǎn)換成Runtime的C語(yǔ)言代碼,Runtime是Object-C的幕后工作者,Object-C會(huì)使用到Runtime來(lái)創(chuàng)建類和對(duì)象,進(jìn)行消息發(fā)送和轉(zhuǎn)發(fā)

特性: 編寫(xiě)的代碼具有運(yùn)行時(shí)、動(dòng)態(tài)特性

isa
在我們初窺oc對(duì)象的時(shí)候了解到了isa,開(kāi)始的時(shí)候我們感覺(jué)它像是一個(gè)C的指針,現(xiàn)在我們想要細(xì)致的了解iOS的運(yùn)行時(shí)機(jī)制,我們需要更加細(xì)致的了解isa,對(duì)于我們了解runtime有很大的幫助。

arm64之前,isa只是一個(gè)指針,保存對(duì)象地址或者類對(duì)象地址,但是在arm64架構(gòu)之后,蘋果對(duì)isa進(jìn)行了優(yōu)化,變成了一個(gè)union結(jié)構(gòu),通過(guò)位域方式來(lái)存儲(chǔ)更多的信息。

共用體:在進(jìn)行某些算法的C語(yǔ)言編程的時(shí)候,需要使幾種不同類型的變量存放到同一段內(nèi)存單元中。也就是使用覆蓋技術(shù),幾個(gè)變量互相覆蓋。這種幾個(gè)不同的變量共同占用一段內(nèi)存的結(jié)構(gòu),在C語(yǔ)言中,被稱作“共用體”類型結(jié)構(gòu),簡(jiǎn)稱共用體。

先看下objc_object源碼

我們知道OC對(duì)象的isa指針并不是直接指向類對(duì)象或者元類對(duì)象,而是需要&ISA_MASK通過(guò)位運(yùn)算才能獲取到類對(duì)象或者元類對(duì)象的地址。今天來(lái)探尋一下為什么需要&ISA_MASK才能獲取到類對(duì)象或者元類對(duì)象的地址,以及這樣的好處。源碼中isa_t是union類型, 可以看到共用體中有一個(gè)結(jié)構(gòu)體,結(jié)構(gòu)體內(nèi)部分別定義了一些變量,變量后面的值代表的是該變量占用多少個(gè)二進(jìn)制位,也就是位域技術(shù)。

isa詳解
要想學(xué)習(xí)Runtime,首先要了解它底層的一些常用數(shù)據(jù)結(jié)構(gòu),比如isa指針在arm64架構(gòu)之前,isa就是一個(gè)普通的指針,存儲(chǔ)著Class、Meta-Class對(duì)象的內(nèi)存地址,從arm64架構(gòu)開(kāi)始,對(duì)isa進(jìn)行了優(yōu)化,變成了一個(gè)共用體(union)結(jié)構(gòu),還使用位域來(lái)存儲(chǔ)更多的信息

union isa_t {
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
#   define ISA_BITFIELD                                                      \
      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)

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
#   define ISA_MAGIC_MASK  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
#   define ISA_BITFIELD                                                        \
      uintptr_t nonpointer        : 1;                                         \
      uintptr_t has_assoc         : 1;                                         \
      uintptr_t has_cxx_dtor      : 1;                                         \
      uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
      uintptr_t magic             : 6;                                         \
      uintptr_t weakly_referenced : 1;                                         \
      uintptr_t deallocating      : 1;                                         \
      uintptr_t has_sidetable_rc  : 1;                                         \
      uintptr_t extra_rc          : 8
#   define RC_ONE   (1ULL<<56)
#   define RC_HALF  (1ULL<<7)

# else
#   error unknown architecture for packed isa
# endif

可以簡(jiǎn)化為下面的圖


image.png

這里我們了解下每個(gè)字段的意義
nonpointer 代表iOS是普通的指針,存儲(chǔ)著Class、Meta-Class對(duì)象的內(nèi)存地址代表優(yōu)化過(guò),使用位域存儲(chǔ)更多的信息
has_assoc 是否有設(shè)置過(guò)關(guān)聯(lián)對(duì)象,如果沒(méi)有,釋放時(shí)會(huì)更快
has_cxx_dtor 是否有C++的析構(gòu)函數(shù)(.cxx_destruct),如果沒(méi)有,釋放時(shí)會(huì)更快
shiftcls 存儲(chǔ)著Class、Meta-Class對(duì)象的內(nèi)存地址信息
magic 用于在調(diào)試時(shí)分辨對(duì)象是否未完成初始化
weakly_referenced 是否有被弱引用指向過(guò),如果沒(méi)有,釋放時(shí)會(huì)更快
deallocating 對(duì)象是否正在釋放
extra_rc 里面存儲(chǔ)的值是引用計(jì)數(shù)器減1
has_sidetable_rc 引用計(jì)數(shù)器是否過(guò)大無(wú)法存儲(chǔ)在isa中如果為1,那么引用計(jì)數(shù)會(huì)存儲(chǔ)在一個(gè)叫SideTable的類的屬性中

isa需求

isa取值

00000101
&00000100
·-------------
00000100
isa進(jìn)行&操作,取哪位哪位值為1,結(jié)果有值相應(yīng)位為1無(wú)值為0

補(bǔ)充“>>”代表左移 ,例“1>>0”左移0位 0b000001 值位1 ,“1>>1左移1位 0b000010 值位2

isa取值

使用||操作,和&操作
設(shè)置位賦值為1

設(shè)置位賦值為1,先安位取反 00000100 = ~111101111,在安位&,

取反產(chǎn)操作“~”

00000101
&11111011
·-------------
00000001

isa位域

    // 位域技術(shù),利用了每個(gè)字節(jié)的每一位
    struct {
        char tall : 1; 
        char rich : 1;
        char handsome : 1;
    } _tallRichHandsome; 一個(gè)

補(bǔ)充共用體
在進(jìn)行某些算法的C語(yǔ)言編程的時(shí)候,需要使幾種不同類型的變量存放到同一段內(nèi)存單元中。也就是使用覆蓋技術(shù),幾個(gè)變量互相覆蓋。這種幾個(gè)不同的變量共同占用一段內(nèi)存的結(jié)構(gòu),在C語(yǔ)言中,被稱作“共用體”類型結(jié)構(gòu),簡(jiǎn)稱共用體,也叫聯(lián)合體,用isa舉例子:isa所有數(shù)據(jù)都存在bits里面,下面的結(jié)構(gòu)體是用于理解的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容