美文网首页
底层原理:class和meta-class的结构

底层原理:class和meta-class的结构

作者: 飘摇的水草 | 来源:发表于2022-02-28 16:52 被阅读0次
    • class和meta-class对象的类型都是 struct objc_class 结构体
    struct objc_class 结构分析
    • 在源码中的部分代码如下:源码版本:objc4-
    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 *data() const {
            return bits.data();
        }
        ...
    
    struct objc_object {
        Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
    };
    
    • 从上面可以看出 struct objc_class 的内存结构可以理解为:
    struct objc_class {
        Class isa;
        Class superclass;
        cache_t cache;             // 方法缓存
        class_data_bits_t bits;  // 用于获取具体的类信息
    };
    
    • 通过bits获取类信息
    class_rw_t *data() const {
            return bits.data();
        }
    
    • 通过上面这个方法,可以得到一个可读写信息表:
    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;
        // 获取只读信息表
        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};
            }
        }
    
    • class_ro_t 只读信息表部分源码如下:
    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;
    
    • 大致关系可以表示如下图:

    isa和superclass答疑
    • 类对象和原类对象是什么时候分配内存?什么时候释放的?
      答:类对象和原类对象是一直在内存中,直到程序退出才销毁,类不管用不用都会被载进在内存,只要程序一启动,执行完main函数,就加载这些类信息。
      如果用到这个类,就会调用这个类的load方法,如果不用,则不会调用Load方法,实例对象里存放的成员变量指的是成员变量的值,而类对象里放的是成员变量的信息,如类型和名称等。

    相关文章

      网友评论

          本文标题:底层原理:class和meta-class的结构

          本文链接:https://www.haomeiwen.com/subject/qbmhrrtx.html