NSObject-C 类结构分析

924 阅读7分钟

一.前期准备

下载 objc 源码,创建可断点调试工程,参考下面的文章
github.com/LGCooci/obj…

二、类的 isa 信息

每个 OC 对象, 包括实例对象、类对象、元类对象,都有一个 isa 成员变量, 其中存储了对象的类信息。

测试代码

@interface Person: NSObject

@end

@implementation Person

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
//        NSObject *objc  = [NSObject alloc];
        NSLog(@""); // 在此处打上断点
    }
    return 0;
}
(lldb) x/4gx Person.class // 输出 Person 类对象信息,其中第一个存储的是 isa 信息
0x100002418: 0x00000001000023f0 0x0000000100334140
0x100002428: 0x000000010032e430 0x0000801000000000

(lldb) po 0x00000001000023f0 // Person 类对象的 isa 存储的还是 Person,这个就是 Person 类的元类对象
Person

(lldb) x/4gx 0x00000001000023f0 // 输出 Person 元类对象 isa 信息
0x1000023f0: 0x00000001003340f0 0x00000001003340f0
0x100002400: 0x0000000100708fd0 0x0002e03100000003

(lldb) po 0x00000001003340f0 // Person 元类对象的 isa 是 NSObject
NSObject

(lldb) x/4gx 0x00000001003340f0 // 输出 NSObject 的 isa 信息,可以发现,指向的是其本身
0x1003340f0: 0x00000001003340f0 0x0000000100334140
0x100334100: 0x000000010069d6b0 0x0004e03100000007
(lldb) x/4gx 0x00000001003340f0
0x1003340f0: 0x00000001003340f0 0x0000000100334140
0x100334100: 0x000000010069d6b0 0x0004e03100000007
(lldb) 

下面我们再对 NSObject 做验证

(lldb) x/4gx NSObject.class
0x100334140: 0x00000001003340f0 0x0000000000000000
0x100334150: 0x000000010069daf0 0x0001801000000003
(lldb) po 0x00000001003340f0 // NSObject 类对象的 isa 指向一个非本身的 NSObject,这个 NSObject 同上面 Person 元类 isa 指向的是同一个类对象,这个就是 根元类对象
NSObject

(lldb) x/4gx 0x00000001003340f0
0x1003340f0: 0x00000001003340f0 0x0000000100334140
0x100334100: 0x000000010069d6b0 0x0005e03100000007

由上面的实验,可以得出如下结论

三、类的继承关系

父类信息在结构体的位置

// 对象
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

// 类对象
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

    class_rw_t *data() const {
        return bits.data();
    }
    // ...
}

从源码中可知,objc_class 结构体对象,使用 x/4gx 命令输出内存信息,第一个 8 字节存储 ISA 变量,第二个 8字节存储 superclass 变量。

验证代码

(lldb) x/4gx Person.class // 输出 Person 类的内存信息
0x100002418: 0x00000001000023f0 0x0000000100334140
0x100002428: 0x000000010032e430 0x0000801000000000

(lldb) po 0x0000000100334140 // Person 类信息的 superclass 是 NSObject
NSObject

(lldb) x/4gx 0x0000000100334140 // 输出 NSObject 类的内存信息
0x100334140: 0x00000001003340f0 0x0000000000000000
0x100334150: 0x000000010069daf0 0x0001801000000003

(lldb) po 0x0000000000000000 // NSObject 类的父类为 nil
<nil>

(lldb) x/4gx 0x00000001000023f0 // 输出 Person 元类的内存信息
0x1000023f0: 0x00000001003340f0 0x00000001003340f0
0x100002400: 0x000000010220df30 0x0005e03100000007

(lldb) po 0x00000001003340f0 // Person 元类的 superclass 与 isa 地址相同,为 NSObject 元类
NSObject

(lldb) x/4gx 0x00000001003340f0 // 输出 NSObject 元类的内存信息,可以看出其 superclass 为 0x0000000100334140,从上面可以的之,这个地址指向 NSObject 类对象 
0x1003340f0: 0x00000001003340f0 0x0000000100334140
0x100334100: 0x0000000102104170 0x0006e0310000000f

上述信息可以得出下面的结构

四、isa 和 类的继承 综合

五、类的底层结构

1.类的底层结构图

2.源码

objc_class

/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

// 对象结构体
/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

// 类对象结构体,继承自 objc_object
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

    class_rw_t *data() const {
        return bits.data();
    }
    // ... 省略方法
}

class_data_bits_t

struct class_data_bits_t {
    friend objc_class;

    // Values are the FAST_ flags above.
    uintptr_t bits;

    // ...
    class_rw_t* data() const {
        return (class_rw_t *)(bits & FAST_DATA_MASK);
    }
    // ...
}

class_rw_t

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint16_t witness;
#if SUPPORT_INDEXED_ISA
    uint16_t index;
#endif

    explicit_atomic<uintptr_t> ro_or_rw_ext;

    Class firstSubclass;
    Class nextSiblingClass;
    // ...

    // 根据 ro_or_rw_ext 类型构建 objc::PointerUnion 类型 ro_or_rw_ext_t
    using ro_or_rw_ext_t = objc::PointerUnion<const class_ro_t *, class_rw_ext_t *>;

    // 将 ro_or_rw_ext 解析为 ro_or_rw_ext_t 类型,兼容 class_ro_t/class_rw_ext_t
    const ro_or_rw_ext_t get_ro_or_rwe() const {
        return ro_or_rw_ext_t{ro_or_rw_ext};
    }

    // 只读信息列表
    const class_ro_t *ro() const {
        auto v = get_ro_or_rwe();
        if (slowpath(v.is<class_rw_ext_t *>())) {
            return v.get<class_rw_ext_t *>()->ro;
        }
        return v.get<const class_ro_t *>();
    }
    // ...
    // 方法列表(包括实例方法和类方法)
    const method_array_t methods() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->methods;
        } else {
            return method_array_t{v.get<const class_ro_t *>()->baseMethods()};
        }
    }

    // 属性列表
    const property_array_t properties() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->properties;
        } else {
            return property_array_t{v.get<const class_ro_t *>()->baseProperties};
        }
    }

    // 协议列表
    const protocol_array_t protocols() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->protocols;
        } else {
            return protocol_array_t{v.get<const class_ro_t *>()->baseProtocols};
        }
    }
}

objc::PointerUnion

template <class PT1, class PT2>
class PointerUnion {
    uintptr_t _value;

    static_assert(alignof(PT1) >= 2, "alignment requirement");
    static_assert(alignof(PT2) >= 2, "alignment requirement");

    struct IsPT1 {
      static const uintptr_t Num = 0;
    };
    struct IsPT2 {
      static const uintptr_t Num = 1;
    };
    template <typename T> struct UNION_DOESNT_CONTAIN_TYPE {};

    uintptr_t getPointer() const {
        return _value & ~1;
    }
    uintptr_t getTag() const {
        return _value & 1;
    }

public:
    explicit PointerUnion(const std::atomic<uintptr_t> &raw)
    : _value(raw.load(std::memory_order_relaxed))
    { }
    PointerUnion(PT1 t) : _value((uintptr_t)t) { }
    PointerUnion(PT2 t) : _value((uintptr_t)t | 1) { }

    void storeAt(std::atomic<uintptr_t> &raw, std::memory_order order) const {
        raw.store(_value, order);
    }

    template <typename T>
    bool is() const {
        using Ty = typename PointerUnionTypeSelector<PT1, T, IsPT1,
            PointerUnionTypeSelector<PT2, T, IsPT2,
            UNION_DOESNT_CONTAIN_TYPE<T>>>::Return;
        return getTag() == Ty::Num;
    }

    template <typename T> T get() const {
      ASSERT(is<T>() && "Invalid accessor called");
      return reinterpret_cast<T>(getPointer());
    }

    template <typename T> T dyn_cast() const {
      if (is<T>())
        return get<T>();
      return T();
    }
};

class_ro_t

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#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_rw_ext_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;
};