objc對象的內(nèi)存布局和Class的本質(zhì)

一個objc對象如何進行內(nèi)存布局?

所有父類的成員變量和自己的成員變量都會存放在該對象所對應(yīng)的存儲空間中.

Objective-C 對象的結(jié)構(gòu)圖
ISA指針
根類的實例變量
倒數(shù)第二層父類的實例變量
...
父類的實例變量
類的實例變量
  • 根對象就是NSObject,它的superclass指針指向nil

  • 類對象既然稱為對象,那它也是一個實例。類對象中也有一個isa指針指向它的元類(meta class),即類對象是元類的實例。元類內(nèi)部存放的是類方法列表,根元類的isa指針指向自己,superclass指針指向NSObject類。


什么是Class?

每一個對象內(nèi)部都有一個isa指針,指向他的類對象,類對象中存放著本對象的

  1. 對象方法列表(對象能夠接收的消息列表,保存在它所對應(yīng)的類對象中)
  2. 成員變量的列表,
  3. 屬性列表,

Class類的源碼:


struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;//isa指針指向Meta Class,因為Objc的類的本身也是一個Object,為了處理這個關(guān)系,runtime就創(chuàng)造了Meta Class,當給類發(fā)送[NSObject alloc]這樣消息時,實際上是把這個消息發(fā)給了Class Object
};

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;// 父類
    cache_t cache;  // formerly cache pointer and vtable
    //方法緩存,對象接到一個消息會根據(jù)isa指針查找消息對象,這時會在method Lists中遍歷,如果cache了,常用的方法調(diào)用時就能夠提高調(diào)用的效率。
    
    // bits & FAST_DATA_MASK = class_rw_t 獲取具體類信息
    class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
    
    class_rw_t *data() { 
        return bits.data();
    }
    
    .
    .
    .

}

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;// 類的版本信息

    const class_ro_t *ro;//class只讀列表

    method_array_t methods;//方法列表
    property_array_t properties;//屬性列表
    protocol_array_t protocols;//協(xié)議列表
    .
    .
    .
}

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;//instance對象暫用的內(nèi)存大小
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;//類名
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;//成員變量列表

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;

    method_list_t *baseMethods() const {
        return baseMethodList;
    }
};
  • class_ro_t結(jié)構(gòu)體一般保存的是原本類編譯完存在的最原始的類信息,所以為只讀的。

  • class_rw_t結(jié)構(gòu)體也是保存的類信息,但如果在程序運行過程中對類的methods(方法列表)、properties(屬性列表)、protocols(協(xié)議列表)等進行更改時,則是在class_rw_t結(jié)構(gòu)體上進行的。如給類添加分類


獲取類對象和元類的方法:

  1. Class objc_getClass(const char *aClassName)

傳入字符串類名,返回對應(yīng)的類對象

#import <objc/runtime.h>
const char * name = "Student";
Class c = objc_getClass(name);

2.Class object_getClass(id obj)

傳入的obj可能是instance對象、class對象、meta-class對象

返回值 :

  • 如果是instance對象,返回class對象

  • 如果是class對象,返回meta-class對象

  • 如果是meta-class對象,返回NSObject(基類)的meta-class對象

#import <objc/runtime.h>
Class objectClass = [NSObject class];
// 將類對象當做參數(shù)傳入,獲得元類對象
Class objectMetaClass = object_getClass(objectClass);

  1. - (Class)class、+ (Class)class

返回的是類對象

 - (Class) {
     return self->isa;
 }
 + (Class) {
     return self;
 }


Meta Class本身也是一個Class,它跟其他Class一樣也有自己的 isa 和 super_class 指針??聪聢D:

image
  • 每個Class都有一個isa指針指向一個唯一的Meta Class

Class(struct objc_class)的isa指針向的地址值與 ISA_MASK 進行或運算后才為實際元類的地址值

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
  • 每一個Meta Class的isa指針都指向最上層的Meta Class(圖中的NSObject的Meta Class)

  • 最上層的Meta Class的isa指針指向自己,形成一個回路

  • 每一個Meta Class的super class指針指向它原本Class的 Super Class的Meta Class。但是最上層的Meta Class的 Super Class指向NSObject Class本身

  • instance調(diào)用對象方法的軌跡
    isa找到class,方法不存在,就通過superclass找父類

  • class調(diào)用類方法的軌跡
    isa找meta-class,方法不存在,就通過superclass找父類


參考:

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

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,058評論 0 9
  • 首先說明,這篇文章幾乎都是抄錄的別人的博客,簡書文章,在此總結(jié),只是為了方便記憶和以后閱讀,如果有什么失禮的地方,...
    LiYaoPeng閱讀 5,339評論 1 14
  • 首先說明,這篇文章幾乎都是抄錄的別人的博客,簡書文章,在此總結(jié),只是為了方便記憶和以后閱讀,如果有什么失禮的地方,...
    devCK凱閱讀 547評論 0 0
  • 前言 我第一次開始重視Objective-C Runtime是從2014年11月1日,@唐巧老師在微博上發(fā)的一條微...
    一縷殤流化隱半邊冰霜閱讀 47,372評論 178 616
  • Objective-C語言是一門動態(tài)語言,它將很多靜態(tài)語言在編譯和鏈接時期做的事放到了運行時來處理。這種動態(tài)語言的...
    有一種再見叫青春閱讀 677評論 0 3

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