runtime10 - class内存结构

475 阅读1分钟

内存结构

iOS 14 以前:

#define FAST_DATA_MASK          0x00007ffffffffff8UL
struct class_data_bits_t {
    uintptr_t bits;
public:
    class_rw_t* data() {
        return (class_rw_t *)(bits & FAST_DATA_MASK);
    }
};

/* OC对象 */
struct objc_object {
    void *isa;
};

/* 类对象 */
struct objc_class : objc_object {
    Class superclass;
    cache_t cache;
    class_data_bits_t bits;
public:
    class_rw_t* data() {
        return bits.data();
    }
    
    objc_class* metaClass() {
        return (objc_class *)((long long)isa & ISA_MASK);
    }
};

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;
};

struct class_rw_t {
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro;
    method_list_t * methods;    // 方法列表
    property_list_t *properties;    // 属性列表
    const protocol_list_t * protocols;  // 协议列表
    Class firstSubclass;
    Class nextSiblingClass;
    char *demangledName;
};

iOS 14以后: 针对class_rw_t 做了一些优化

struct class_rw_ext_t {
    const class_ro_t *ro;
    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    char *demangledName;
    uint32_t version;
};

struct class_rw_t {
    uint32_t flags;
    uint16_t witness;
    explicit_atomic<uintptr_t> ro_or_rw_ext;
    Class firstSubclass;
    Class nextSiblingClass;
}

iOS14 以前:

img

iOS14以后:

img

优化原因:详细看这里

class_ro_t和class_rw_t的关系与区别

ro指readonly, rw指readwrite

在realizeclass以前, class的bits中放的是class_ro_t的地址,在realizeclass时, 会根据class_ro_t来初始化class_rw_t

编译期能确定下来的信息都在class_ro_t中, class_ro_t都是编译过后就不会发生改变的

class_rw_t中则提供了运行时对类进行扩展的能力, 在运行过程中可能变化, method_array_t / property_array_t / protocol_array_t 这些都是二维数组

在优化后,如果该类没有分类, 没有在运行时添加方法等,class_rw_tro_or_rw_ext成员有可能指向的是class_ro_t的地址