objc对象的内存布局和Class的本质

2018-11-20  本文已影响15人  aaayia

一个objc对象如何进行内存布局?

所有父类的成员变量和自己的成员变量都会存放在该对象所对应的存储空间中.

Objective-C 对象的结构图
ISA指针
根类的实例变量
倒数第二层父类的实例变量
...
父类的实例变量
类的实例变量

什么是Class?

每一个对象内部都有一个isa指针,指向他的类对象,类对象中存放着本对象的

  1. 对象方法列表(对象能够接收的消息列表,保存在它所对应的类对象中)
  2. 成员变量的列表,
  3. 属性列表,

Class类的源码:


struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;//isa指针指向Meta Class,因为Objc的类的本身也是一个Object,为了处理这个关系,runtime就创造了Meta Class,当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object
};

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;// 父类
    cache_t cache;  // formerly cache pointer and vtable
    //方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。
    
    // 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;//协议列表
    .
    .
    .
}

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;//instance对象暂用的内存大小
#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;
    }
};

获取类对象和元类的方法:

  1. Class objc_getClass(const char *aClassName)

传入字符串类名,返回对应的类对象

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

2.Class object_getClass(id obj)

传入的obj可能是instance对象、class对象、meta-class对象

返回值 :

#import <objc/runtime.h>
Class objectClass = [NSObject class];
// 将类对象当做参数传入,获得元类对象
Class objectMetaClass = object_getClass(objectClass);

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

返回的是类对象

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


Meta Class本身也是一个Class,它跟其他Class一样也有自己的 isa 和 super_class 指针。看下图:

image

Class(struct objc_class)的isa指针向的地址值与 ISA_MASK 进行或运算后才为实际元类的地址值

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL

参考:

  1. 刨根问底Objective-C Runtime
上一篇 下一篇

猜你喜欢

热点阅读