Runtime中的 isa 結(jié)構(gòu)體

原文鏈接

有一定經(jīng)驗(yàn)的iOS開發(fā)者髓绽,或多或少的都聽過Runtime箩言。Runtime雕欺,也就是運(yùn)行時(shí),是Objective-C語言的特性之一索烹。日常開發(fā)中,可能直接和Runtime打交道的機(jī)會(huì)不多弱睦。然而百姓,"發(fā)消息"、"消息轉(zhuǎn)發(fā)"這些名詞開發(fā)者應(yīng)該經(jīng)常聽到况木,這些名詞所用到的技術(shù)基礎(chǔ)就是Runtime垒拢。了解Runtime旬迹,有助于開發(fā)者深入理解Objective-C這門語言。

在具體了解Runtime之前求类,先提一個(gè)問題奔垦,什么是動(dòng)態(tài)語言?

Objective-C是一門動(dòng)態(tài)語言

使用Objective-C做iOS開發(fā)的同學(xué)一定都聽說過一句話:Objective-C是一門動(dòng)態(tài)語言尸疆。動(dòng)態(tài)語言椿猎,肯定是和靜態(tài)語言相對(duì)應(yīng)的。那么寿弱,靜態(tài)語言有哪些特性鸵贬,動(dòng)態(tài)語言又有哪些特性?

回顧一下大學(xué)時(shí)期脖捻,學(xué)的第一門語言C語言阔逼,學(xué)習(xí)C語言的過程中從來沒聽說過運(yùn)行時(shí),也沒聽說過什么靜態(tài)語言地沮,動(dòng)態(tài)語言嗜浮。因此我們有理由相信,C語言是一門靜態(tài)語言摩疑。

事實(shí)上也確實(shí)如此危融,C語言是一門靜態(tài)語言,Objective-C是一門動(dòng)態(tài)語言雷袋。然而吉殃,還是說不出靜態(tài)語言和動(dòng)態(tài)語言到底有什么區(qū)別……

靜態(tài)語言和動(dòng)態(tài)語言

靜態(tài)語言,可以理解成在編譯期間就確定一切的語言楷怒。以C語言來舉例蛋勺,C語言編譯后會(huì)成為一個(gè)可執(zhí)行文件。假設(shè)我們在C代碼中寫了一個(gè)hello函數(shù)鸠删,并且在主程序中調(diào)用了這個(gè)hello函數(shù)抱完。倘若在編譯期間,hello函數(shù)的入口地址相對(duì)于主程序入口地址的偏移量是0x0000abcdef(不要在意這個(gè)值刃泡,只是用來舉例)巧娱,那么在執(zhí)行該程序時(shí),執(zhí)行到hello函數(shù)時(shí)烘贴,一定執(zhí)行的是相對(duì)主程序入口地址偏移量為0x0000abcdef的代碼塊禁添。也就是說,靜態(tài)語言桨踪,在編譯期間就已經(jīng)確定一切老翘,運(yùn)行期間只是遵守編譯期確定的指令在執(zhí)行

作為對(duì)比,再看一下動(dòng)態(tài)語言酪捡,以經(jīng)常用到的Objective-C為例叁征。假設(shè)在Objective-C中寫了hello方法,并且在主程序中調(diào)用了hello方法逛薇,也就是發(fā)送hello消息捺疼。在編譯期間,只能確定要向某個(gè)對(duì)象發(fā)送hello消息永罚,但是具體執(zhí)行哪個(gè)內(nèi)存塊的代碼是不確定的啤呼,具體執(zhí)行的代碼需要在運(yùn)行期間才能確定

到這里呢袱,靜態(tài)語言和動(dòng)態(tài)語言的區(qū)別已經(jīng)很明顯了官扣。靜態(tài)語言在編譯期間就已經(jīng)確定一切,而動(dòng)態(tài)語言編譯期間只能確定一部分羞福,還有一部分需要在運(yùn)行期間才能確定惕蹄。也就是說,動(dòng)態(tài)語言成為一個(gè)可執(zhí)行程序并能夠正確的執(zhí)行治专,除了需要一個(gè)編譯器外卖陵,還需要一套運(yùn)行時(shí)系統(tǒng),用于確定到底執(zhí)行哪一塊代碼张峰。Objective-C中的運(yùn)行時(shí)系統(tǒng)內(nèi)就是Runtime泪蔫。

Runtime源碼

Runtime源碼是一套用C語言實(shí)現(xiàn)的API,整套代碼是開源的喘批,可以從蘋果開源網(wǎng)站上下載Runtime源碼撩荣。默認(rèn)下載的Runtime源碼是不能編譯的,通過修改配置和導(dǎo)入必要的頭文件饶深,可以編譯成功Runtime源碼餐曹。我在github上放了編譯成功的Runtime源碼,且有我在看Runtime源碼時(shí)的一些注釋粥喜,本篇文章中的代碼也是基于此Runtime源碼凸主。

由于Runtime源碼代碼量比較大,一篇文章介紹完Runtime源碼是不可能的额湘。因此這篇文章主要介紹Runtime中的isa結(jié)構(gòu)體,作為Runtime的入門旁舰。

isa結(jié)構(gòu)體

有經(jīng)驗(yàn)的iOS開發(fā)者可能都聽過一句話:在Objective-C語言中锋华,類也是對(duì)象,且每個(gè)對(duì)象都包含一個(gè)isa指針箭窜,isa指針指向該對(duì)象所屬的類毯焕。不過現(xiàn)在Runtime中的對(duì)象定義已經(jīng)不是這樣了,現(xiàn)在使用的是isa_t類型的結(jié)構(gòu)體。每一個(gè)對(duì)象都有一個(gè)isa_t類型的結(jié)構(gòu)體isa纳猫。之前的isa指針作用是指向該對(duì)象的類婆咸,那么isa結(jié)構(gòu)體作為isa指針的替代者,是如何完成這個(gè)功能的呢芜辕?

在解決這個(gè)問題之前尚骄,我們先來看一下Runtime源碼中對(duì)象和類的定義。

objc_object

看一下Runtime中對(duì)id類型的定義

typedef struct objc_object *id;

這里的id也就是Objective-C中的id類型侵续,代表任意對(duì)象倔丈,類似于C語言中的 void ∽次希可以看到需五,id實(shí)際上是一個(gè)指向結(jié)構(gòu)體objc_object的指針。

再來看一下objc_object的定義轧坎,該定義位于objc-private.h文件中:

struct objc_object {
    // isa結(jié)構(gòu)體
private:
    isa_t isa;
}

結(jié)構(gòu)體中還包含一些public的方法宏邮。可以看到缸血,對(duì)象結(jié)構(gòu)體(objc_object)中的第一個(gè)變量就是isa_t 類型的isa蜜氨。關(guān)于isa_t具體是什么,后續(xù)再介紹属百。

Objective-C語言中最主要的就是對(duì)象和類记劝,看完了對(duì)象在Runtime中的定義,再看一下類在Runtime中的定義族扰。

objc_class

Runtime中對(duì)于Class的定義

typedef struct objc_class *Class;

Class實(shí)際上是一個(gè)指向objc_class結(jié)構(gòu)體的指針厌丑。

看一下結(jié)構(gòu)體objc_class的定義,objc_class的定義位于objc-runtime-new.h文件中

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
}

結(jié)構(gòu)體中還包含一些方法渔呵。

注意怒竿,objc_class是繼承于objc_object的,因此objc_class中也包含isa_t類型的isa扩氢。objc_class的定義可以理解成下面這樣:

struct objc_class {
    isa_t isa;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
}

isa的作用

上面也提到了耕驰,isa能夠使該對(duì)象找到自己所屬的類。為什么對(duì)象需要知道自己所屬的類呢录豺?這主要是因?yàn)閷?duì)象的方法是存儲(chǔ)在該對(duì)象所屬的類中的朦肘。

這一點(diǎn)是很容易理解的,一個(gè)類可以有多個(gè)對(duì)象双饥,倘若每個(gè)對(duì)象都含有自己能夠執(zhí)行的方法媒抠,那對(duì)于內(nèi)存來說是災(zāi)難級(jí)的。

在向?qū)ο蟀l(fā)送消息咏花,也就是實(shí)例方法被調(diào)用時(shí)趴生,對(duì)象通過自己的isa找到所屬的類,然后在類的結(jié)構(gòu)中找到對(duì)應(yīng)方法的實(shí)現(xiàn)(關(guān)于在類結(jié)構(gòu)中如何找到方法的實(shí)現(xiàn),后續(xù)的文章再介紹)苍匆。

我們知道刘急,Objective-C中區(qū)分類方法和實(shí)例方法。實(shí)例方法是如何找到的我們了解了浸踩,那么類方法是如何找到的呢叔汁?類結(jié)構(gòu)體中也有isa,類對(duì)象的isa指向哪里呢民轴?

元類(metaClass)

為了解決類方法調(diào)用攻柠,Objective-C引入了元類(metaClass),類對(duì)象的isa指向該類的元類后裸,一個(gè)類對(duì)象對(duì)應(yīng)一個(gè)元類對(duì)象瑰钮。

元類對(duì)象也是類對(duì)象,既然是類對(duì)象微驶,那么元類對(duì)象中也有isa浪谴,那么元類的isa又指向哪里呢?總不能指向元元類吧……這樣是無窮無盡的因苹。

Objective-C語言的設(shè)計(jì)者已經(jīng)考慮到了這個(gè)問題苟耻,所有元類的isa都指向一個(gè)元類對(duì)象,該元類對(duì)象就是 meta Root Class,可以理解成根元類扶檐。關(guān)于實(shí)例對(duì)象凶杖、類、元類之間的關(guān)系款筑,蘋果官方給了一張圖智蝠,非常清晰的表明了三者的關(guān)系,如下

image

isa結(jié)構(gòu)體定義

了解了isa的作用奈梳,現(xiàn)在來看一下isa的定義杈湾。isa是isa_t類型,isa_t也是一個(gè)結(jié)構(gòu)體攘须,其定義在objc-private.h中:

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

    Class cls;
    // 相當(dāng)于是unsigned long bits;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};

ISA_BITFIELD的定義在 isa.h文件中:

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

注意:這里的代碼都是x86_64架構(gòu)下的漆撞,arm64架構(gòu)下和x86_64架構(gòu)下有區(qū)別,但是不影響我們理解isa_t結(jié)構(gòu)體于宙。

將isa_t結(jié)構(gòu)體中的ISA_BITFIELD使用isa.h文件中的ISA_BITFIELD替換浮驳,isa_t的定義可以表示如下:

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

    Class cls;
    // 相當(dāng)于是unsigned long bits;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct {
        uintptr_t nonpointer        : 1; 
        uintptr_t has_assoc         : 1;
        uintptr_t has_cxx_dtor      : 1;
        uintptr_t shiftcls          : 44;
        uintptr_t magic             : 6;
        uintptr_t weakly_referenced : 1;
        uintptr_t deallocating      : 1;
        uintptr_t has_sidetable_rc  : 1;
        uintptr_t extra_rc          : 8;
    };
#endif
};

注意isa_t是聯(lián)合體,也就是說isa_t中的變量捞魁,cls抹恳、bits和內(nèi)部的結(jié)構(gòu)體全都位于同一塊地址空間。

本篇文章主要分析下isa_t中內(nèi)部結(jié)構(gòu)體中各個(gè)變量的作用

struct {
    uintptr_t nonpointer        : 1; 
    uintptr_t has_assoc         : 1;
    uintptr_t has_cxx_dtor      : 1;
    uintptr_t shiftcls          : 44;
    uintptr_t magic             : 6;
    uintptr_t weakly_referenced : 1;
    uintptr_t deallocating      : 1;
    uintptr_t has_sidetable_rc  : 1;
    uintptr_t extra_rc          : 8;
};

該結(jié)構(gòu)體共占64位署驻,其內(nèi)存分布如下:

image

在了解內(nèi)個(gè)結(jié)構(gòu)體各個(gè)變量的作用前,先通過Runtime代碼看一下isa結(jié)構(gòu)體是如何初始化的。

isa結(jié)構(gòu)體初始化

isa結(jié)構(gòu)體初始化定義在objc_object結(jié)構(gòu)體中旺上,看一下官方提供的函數(shù)和注釋:

// initIsa() should be used to init the isa of new objects only.
// If this object already has an isa, use changeIsa() for correctness.
// initInstanceIsa(): objects with no custom RR/AWZ
// initClassIsa(): class objects
// initProtocolIsa(): protocol objects
// initIsa(): other objects
void initIsa(Class cls /*nonpointer=false*/);
void initClassIsa(Class cls /*nonpointer=maybe*/);
void initProtocolIsa(Class cls /*nonpointer=maybe*/);
void initInstanceIsa(Class cls, bool hasCxxDtor);

官方提供的有類對(duì)象初始化isa,協(xié)議對(duì)象初始化isa瓶蚂,實(shí)例對(duì)象初始化isa,其他對(duì)象初始化isa宣吱,分別對(duì)應(yīng)不同的函數(shù)窃这。

看下每個(gè)函數(shù)的實(shí)現(xiàn):

inline void objc_object::initIsa(Class cls)
{
    initIsa(cls, false, false);
}

inline void objc_object::initClassIsa(Class cls)
{
    if (DisableNonpointerIsa  ||  cls->instancesRequireRawIsa()) {
        initIsa(cls, false/*not nonpointer*/, false);
    } else {
        initIsa(cls, true/*nonpointer*/, false);
    }
}

inline void objc_object::initProtocolIsa(Class cls)
{
    return initClassIsa(cls);
}

inline void objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
{
    assert(!cls->instancesRequireRawIsa());
    assert(hasCxxDtor == cls->hasCxxDtor());

    initIsa(cls, true, hasCxxDtor);
}

可以看到,無論是類對(duì)象征候,實(shí)例對(duì)象杭攻,協(xié)議對(duì)象,還是其他對(duì)象疤坝,初始化isa結(jié)構(gòu)體最終都調(diào)用了

inline void objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor)

函數(shù)兆解,只是所傳的參數(shù)不同而已。

最終調(diào)用的initIsa函數(shù)的代碼跑揉,經(jīng)過簡化后如下:

inline void objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 
{ 
    if (!nonpointer) {
        isa.cls = cls;
    } else {
        // 實(shí)例對(duì)象的isa初始化直接走else分之
        // 初始化一個(gè)心得isa_t結(jié)構(gòu)體
        isa_t newisa(0);
        // 對(duì)新結(jié)構(gòu)體newisa賦值
        // ISA_MAGIC_VALUE的值是0x001d800000000001ULL锅睛,轉(zhuǎn)化成二進(jìn)制是64位
        // 根據(jù)注釋,使用ISA_MAGIC_VALUE賦值历谍,實(shí)際上只是賦值了isa.magic和isa.nonpointer
        newisa.bits = ISA_MAGIC_VALUE;
        newisa.has_cxx_dtor = hasCxxDtor;
        // 將當(dāng)前對(duì)象的類指針賦值到shiftcls
        // 類的指針是按照字節(jié)(8bits)對(duì)齊的现拒,其指針后三位都是沒有意義的0,因此可以右移3位
        newisa.shiftcls = (uintptr_t)cls >> 3;
        // 賦值望侈∮∈撸看注釋這個(gè)地方不是線程安全的?脱衙?
        isa = newisa;
    }
}

初始化實(shí)例對(duì)象的isa時(shí)侥猬,傳入的nonpointer參數(shù)是true,所以直接走了else分之岂丘。在else分之中陵究,對(duì)isa的bits分之賦值ISA_MAGIC_VALUE。根據(jù)注釋奥帘,這樣代碼實(shí)際上只是對(duì)isa中的magic和nonpointer進(jìn)行了賦值铜邮,來看一下為什么。

ISA_MAGIC_VALUE的值是0x001d800000000001ULL寨蹋,轉(zhuǎn)化成二進(jìn)制就是0000 0000 0001 1101 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001,將每一位對(duì)應(yīng)到isa內(nèi)部的結(jié)構(gòu)體中松蒜,看一下對(duì)哪些變量產(chǎn)生了影響:

image

可以看到將nonpointer賦值為1;將magci賦值為110111已旧;其他的仍然都是0秸苗。所以說只賦值了isa.magci和isa.nonpointer。

nonpointer

在文章開頭也提到了运褪,在Objective-C語言中惊楼,類也是對(duì)象玖瘸,且每個(gè)對(duì)象都包含一個(gè)isa指針,現(xiàn)在改為了isa結(jié)構(gòu)體檀咙。nonpointer作用就是區(qū)分這兩者雅倒。

  1. 如果nonpointer為1,代表不是isa指針弧可,而是isa結(jié)構(gòu)體蔑匣。雖然不是isa指針,但是通過isa結(jié)構(gòu)體仍然能獲得類指針(下面會(huì)分析)棕诵。
  2. 如果nonpointer為0裁良,代表當(dāng)前是isa指針,訪問對(duì)象的isa會(huì)直接返回類指針校套。
magic

magic的值調(diào)試器會(huì)用到价脾,調(diào)試器根據(jù)magci的值判斷當(dāng)前對(duì)象已經(jīng)初始過了,還是尚未初始化的空間搔确。

has_cxx_dtor

接下來就是對(duì)has_cxx_dtor進(jìn)行賦值彼棍。has_cxx_dtor表示當(dāng)前對(duì)象是否有C++的析構(gòu)函數(shù)(destructor),如果沒有,釋放時(shí)會(huì)快速的釋放內(nèi)存膳算。

shiftcls

在函數(shù)

inline void objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 

中座硕,參數(shù)cls就是類的指針。而

newisa.shiftcls = (uintptr_t)cls >> 3;

shiftcls存儲(chǔ)的到底是什么呢涕蜂?

實(shí)際上华匾,shiftcls存儲(chǔ)的就是當(dāng)前對(duì)象類的指針。之所以右移三位是出于節(jié)省空間上的考慮机隙。

在Objective-C中蜘拉,類的指針是按照字節(jié)(8 bits)對(duì)齊的,也就是說類指針地址轉(zhuǎn)化成十進(jìn)制后有鹿,都是8的倍數(shù)旭旭,也就是說,類指針地址轉(zhuǎn)化成二進(jìn)制后葱跋,后三位都是0持寄。既然是沒有意義的0,那么在存儲(chǔ)時(shí)就可以省略娱俺,用節(jié)省下來的空間存儲(chǔ)一些其他信息稍味。

在objc-runtime-new.mm文件的

static __attribute__((always_inline)) id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, 
                              bool cxxConstruct = true, 
                              size_t *outAllocatedSize = nil)

函數(shù),類初始化時(shí)會(huì)調(diào)用該函數(shù)荠卷∧B可以在該函數(shù)中打印類對(duì)象的地址

if (!cls) return nil;
// 這里可以打印類指針的地址,類指針地址最后一位是十六進(jìn)制的8或者0,說明
// 類指針地址后三位都是0
printf("cls address = %p\n",cls);

打印出的部分信息如下:

cls address = 0x7fff83bca218
cls address = 0x7fff83bcab28
cls address = 0x7fff83bc5290
cls address = 0x7fff83717f58
cls address = 0x7fff83717f58
cls address = 0x100b15140
cls address = 0x7fff83717fa8
cls address = 0x7fff837164c8
cls address = 0x7fff837164c8
cls address = 0x7fff83716e78
cls address = 0x100b15140
cls address = 0x7fff837175a8
cls address = 0x7fff837175a8
cls address = 0x7fff83717fa8

可以看到類對(duì)象的地址最后一位都是8或者0油宜,說明類對(duì)象確實(shí)是按照字節(jié)對(duì)齊掂碱,后三位都是0怜姿。因此在賦值shiftcls時(shí),右移三位是安全的顶吮,不會(huì)丟失類指針信息社牲。

我們可以寫代碼驗(yàn)證一下對(duì)象的isa和類對(duì)象指針的關(guān)系。代碼如下:

#import <Foundation/Foundation.h>
#import "objc-runtime.h"

// 把一個(gè)十進(jìn)制的數(shù)轉(zhuǎn)為二進(jìn)制
NSString * binaryWithInteger(NSUInteger decInt){
    NSString *string = @"";
    NSUInteger x = decInt;
    while(x > 0){
        string = [[NSString stringWithFormat:@"%lu",x&1] stringByAppendingString:string];
        x = x >> 1;
    }
    return string;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 把對(duì)象轉(zhuǎn)為objc_object結(jié)構(gòu)體
        struct objc_object *object = (__bridge struct objc_object *)([NSObject new]);
        NSLog(@"binary = %@",binaryWithInteger(object->isa));
        // uintptr_t實(shí)際上就是unsigned long
        NSLog(@"binary = %@",binaryWithInteger((uintptr_t)[NSObject class]));
    }
    return 0;
}

打印出isa的內(nèi)容是:1011101100000000000000100000000101100010101000101000001悴了,NSObject類對(duì)象的指針是:100000000101100010101000101000000。首先將isa的內(nèi)容補(bǔ)充至64位

0000 0101 1101 1000 0000 0000 0001 0000 0000 1011 0001 0101 0001 0100 0001

取第4位到第47位之間的內(nèi)容违寿,也就是shiftcls的值:

000 0000 0000 0001 0000 0000 1011 0001 0101 0001 0100 0

將類對(duì)象的指針右移三位湃交,即去除后三位的0,得到

100000000101100010101000101000

和上面的shiftcls對(duì)比:

                 10 0000 0001 0110 0010 1010 0010 1000
0000 0000 0000 0010 0000 0001 0110 0010 1010 0010 1000

可以確認(rèn):shiftcls中的確包含了類對(duì)象的指針藤巢。

其他位

上面已經(jīng)介紹了nonpointer搞莺、magic、shiftcls掂咒、has_cxx_dtor才沧,還有一些其他位沒有介紹,這里簡單了解一下绍刮。

  1. has_assoc: 表示對(duì)象是否含有關(guān)聯(lián)引用(associatedObject)
  2. weakly_referenced: 表示對(duì)象是否含有弱引用對(duì)象
  3. deallocating: 表示對(duì)象是否正在釋放
  4. has_sidetable_rc: 表示對(duì)象的引用計(jì)數(shù)是否太大温圆,如果太大,則需要用其他的數(shù)據(jù)結(jié)構(gòu)來存
  5. extra_rc:對(duì)象的引用計(jì)數(shù)大于1孩革,則會(huì)將引用計(jì)數(shù)的個(gè)數(shù)存到extra_rc里面岁歉。比如對(duì)象的引用計(jì)數(shù)為5,則extra_rc的值為4膝蜈。

extra_rc和has_sidetable_c可以一起理解锅移。extra_rc用于存放引用計(jì)數(shù)的個(gè)數(shù),extra_rc占8位饱搏,也就是最大表示255非剃,當(dāng)對(duì)象的引用計(jì)數(shù)個(gè)數(shù)超過257時(shí),has_sidetable_rc的值應(yīng)該為1推沸。

總結(jié)

至此备绽,isa結(jié)構(gòu)體的介紹就完了。需要提醒的是坤学,上面的代碼是運(yùn)行在macOS上疯坤,也就是x86_64架構(gòu)上的,isa結(jié)構(gòu)體也是基于x86_64架構(gòu)的深浮。在arm64架構(gòu)上压怠,isa結(jié)構(gòu)體中變量所占用的位數(shù)和x86_64架構(gòu)是不一樣的,但是表示的含義是一樣的飞苇。理解了x86_64架構(gòu)下的isa結(jié)構(gòu)體菌瘫,相信對(duì)于理解arm架構(gòu)下的isa結(jié)構(gòu)體蜗顽,應(yīng)該不是什么難事。

參考文章

從 NSObject 的初始化了解 isa

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雨让,一起剝皮案震驚了整個(gè)濱河市雇盖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌栖忠,老刑警劉巖崔挖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異庵寞,居然都是意外死亡狸相,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門捐川,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脓鹃,“玉大人,你說我怎么就攤上這事古沥∪秤遥” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵岩齿,是天一觀的道長太颤。 經(jīng)常有香客問我,道長纯衍,這世上最難降的妖魔是什么栋齿? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮襟诸,結(jié)果婚禮上瓦堵,老公的妹妹穿的比我還像新娘。我一直安慰自己歌亲,他們只是感情好菇用,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著陷揪,像睡著了一般惋鸥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悍缠,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天卦绣,我揣著相機(jī)與錄音,去河邊找鬼飞蚓。 笑死滤港,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的趴拧。 我是一名探鬼主播溅漾,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼山叮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了添履?” 一聲冷哼從身側(cè)響起屁倔,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎暮胧,沒想到半個(gè)月后锐借,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叔壤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年瞎饲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炼绘。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖妄田,靈堂內(nèi)的尸體忽然破棺而出俺亮,到底是詐尸還是另有隱情,我是刑警寧澤疟呐,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布脚曾,位于F島的核電站,受9級(jí)特大地震影響启具,放射性物質(zhì)發(fā)生泄漏本讥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一鲁冯、第九天 我趴在偏房一處隱蔽的房頂上張望拷沸。 院中可真熱鬧,春花似錦薯演、人聲如沸撞芍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽序无。三九已至,卻和暖如春衡创,著一層夾襖步出監(jiān)牢的瞬間帝嗡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工璃氢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哟玷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓拔莱,卻偏偏與公主長得像碗降,于是被迫代替她去往敵國和親隘竭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉讼渊,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,682評(píng)論 0 9
  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡介 Runt...
    樂樂的簡書閱讀 2,131評(píng)論 0 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,089評(píng)論 1 32
  • RunTime:指一個(gè)程序在運(yùn)行(或者在被執(zhí)行)的狀態(tài)动看。也就是說,當(dāng)你打開一個(gè)程序使它在電腦上運(yùn)行的時(shí)候爪幻,那個(gè)程序...
    悟2023閱讀 445評(píng)論 0 1
  • 本文基于objc4-709源碼進(jìn)行分析菱皆。關(guān)于源碼編譯:objc - 編譯Runtime源碼objc4-706 ob...
    WeiHing閱讀 809評(píng)論 1 3