美文网首页
OC类原理

OC类原理

作者: 凯歌948 | 来源:发表于2021-01-17 13:23 被阅读0次

    ISA

    isa.png

    类整体结构

    类整体结构.png

    类的结构:


    类结构1.png

    当类第一次从磁盘加载到内存时的结构:


    类结构2.png
    当类第一次被使用时的结构(runtime):
    类结构3.png
    将需要动态更新的部分提取出来,存入class_rw_ext_t:
    类结构4.png
    /// Represents an instance of a class.
    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();
        }
        void setData(class_rw_t *newData) {
            bits.setData(newData);
        }
    
        ......
    
    }
    
    struct class_data_bits_t {
        friend objc_class;
    
        // Values are the FAST_ flags above.
        uintptr_t bits;
    private:
        bool getBit(uintptr_t bit) const
        {
            return bits & bit;
        }
    
        // Atomically set the bits in `set` and clear the bits in `clear`.
        // set and clear must not overlap.
        void setAndClearBits(uintptr_t set, uintptr_t clear)
        {
            ASSERT((set & clear) == 0);
            uintptr_t oldBits;
            uintptr_t newBits;
            do {
                oldBits = LoadExclusive(&bits);
                newBits = (oldBits | set) & ~clear;
            } while (!StoreReleaseExclusive(&bits, oldBits, newBits));
        }
    
        void setBits(uintptr_t set) {
            __c11_atomic_fetch_or((_Atomic(uintptr_t) *)&bits, set, __ATOMIC_RELAXED);
        }
    
        void clearBits(uintptr_t clear) {
            __c11_atomic_fetch_and((_Atomic(uintptr_t) *)&bits, ~clear, __ATOMIC_RELAXED);
        }
    
    public:
    
        class_rw_t* data() const {
            return (class_rw_t *)(bits & FAST_DATA_MASK);
        }
        void setData(class_rw_t *newData)
        {
            ASSERT(!data()  ||  (newData->flags & (RW_REALIZING | RW_FUTURE)));
            // Set during realization or construction only. No locking needed.
            // Use a store-release fence because there may be concurrent
            // readers of data and data's contents.
            uintptr_t newBits = (bits & ~FAST_DATA_MASK) | (uintptr_t)newData;
            atomic_thread_fence(memory_order_release);
            bits = newBits;
        }
    
        // Get the class's ro data, even in the presence of concurrent realization.
        // fixme this isn't really safe without a compiler barrier at least
        // and probably a memory barrier when realizeClass changes the data field
        const class_ro_t *safe_ro() {
            class_rw_t *maybe_rw = data();
            if (maybe_rw->flags & RW_REALIZED) {
                // maybe_rw is rw
                return maybe_rw->ro();
            } else {
                // maybe_rw is actually ro
                return (class_ro_t *)maybe_rw;
            }
        }
    
        void setClassArrayIndex(unsigned Idx) {
    #if SUPPORT_INDEXED_ISA
            // 0 is unused as then we can rely on zero-initialisation from calloc.
            ASSERT(Idx > 0);
            data()->index = Idx;
    #endif
        }
    
        unsigned classArrayIndex() {
    #if SUPPORT_INDEXED_ISA
            return data()->index;
    #else
            return 0;
    #endif
        }
    
        bool isAnySwift() {
            return isSwiftStable() || isSwiftLegacy();
        }
    
        bool isSwiftStable() {
            return getBit(FAST_IS_SWIFT_STABLE);
        }
        void setIsSwiftStable() {
            setAndClearBits(FAST_IS_SWIFT_STABLE, FAST_IS_SWIFT_LEGACY);
        }
    
        bool isSwiftLegacy() {
            return getBit(FAST_IS_SWIFT_LEGACY);
        }
        void setIsSwiftLegacy() {
            setAndClearBits(FAST_IS_SWIFT_LEGACY, FAST_IS_SWIFT_STABLE);
        }
    
        // fixme remove this once the Swift runtime uses the stable bits
        bool isSwiftStable_ButAllowLegacyForNow() {
            return isAnySwift();
        }
    
        _objc_swiftMetadataInitializer swiftMetadataInitializer() {
            // This function is called on un-realized classes without
            // holding any locks.
            // Beware of races with other realizers.
            return safe_ro()->swiftMetadataInitializer();
        }
    };
    
    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;
    
    private:
        using ro_or_rw_ext_t = objc::PointerUnion<const 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};
        }
    
        void set_ro_or_rwe(const class_ro_t *ro) {
            ro_or_rw_ext_t{ro}.storeAt(ro_or_rw_ext, memory_order_relaxed);
        }
    
        void set_ro_or_rwe(class_rw_ext_t *rwe, const class_ro_t *ro) {
            // the release barrier is so that the class_rw_ext_t::ro initialization
            // is visible to lockless readers
            rwe->ro = ro;
            ro_or_rw_ext_t{rwe}.storeAt(ro_or_rw_ext, memory_order_release);
        }
    
        class_rw_ext_t *extAlloc(const class_ro_t *ro, bool deep = false);
    
    public:
        void setFlags(uint32_t set)
        {
            __c11_atomic_fetch_or((_Atomic(uint32_t) *)&flags, set, __ATOMIC_RELAXED);
        }
    
        void clearFlags(uint32_t clear) 
        {
            __c11_atomic_fetch_and((_Atomic(uint32_t) *)&flags, ~clear, __ATOMIC_RELAXED);
        }
    
        // set and clear must not overlap
        void changeFlags(uint32_t set, uint32_t clear) 
        {
            ASSERT((set & clear) == 0);
    
            uint32_t oldf, newf;
            do {
                oldf = flags;
                newf = (oldf | set) & ~clear;
            } while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&flags));
        }
    
        class_rw_ext_t *ext() const {
            return get_ro_or_rwe().dyn_cast<class_rw_ext_t *>();
        }
    
        class_rw_ext_t *extAllocIfNeeded() {
            auto v = get_ro_or_rwe();
            if (fastpath(v.is<class_rw_ext_t *>())) {
                return v.get<class_rw_ext_t *>();
            } else {
                return extAlloc(v.get<const class_ro_t *>());
            }
        }
    
        class_rw_ext_t *deepCopy(const class_ro_t *ro) {
            return extAlloc(ro, true);
        }
    
        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 *>();
        }
    
        void set_ro(const class_ro_t *ro) {
            auto v = get_ro_or_rwe();
            if (v.is<class_rw_ext_t *>()) {
                v.get<class_rw_ext_t *>()->ro = ro;
            } else {
                set_ro_or_rwe(ro);
            }
        }
    
        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};
            }
        }
    };
    
    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_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;
    
        // This field exists only when RO_HAS_SWIFT_INITIALIZER is set.
        _objc_swiftMetadataInitializer __ptrauth_objc_method_list_imp _swiftMetadataInitializer_NEVER_USE[0];
    
        _objc_swiftMetadataInitializer swiftMetadataInitializer() const {
            if (flags & RO_HAS_SWIFT_INITIALIZER) {
                return _swiftMetadataInitializer_NEVER_USE[0];
            } else {
                return nil;
            }
        }
    
        method_list_t *baseMethods() const {
            return baseMethodList;
        }
    
        class_ro_t *duplicate() const {
            if (flags & RO_HAS_SWIFT_INITIALIZER) {
                size_t size = sizeof(*this) + sizeof(_swiftMetadataInitializer_NEVER_USE[0]);
                class_ro_t *ro = (class_ro_t *)memdup(this, size);
                ro->_swiftMetadataInitializer_NEVER_USE[0] = this->_swiftMetadataInitializer_NEVER_USE[0];
                return ro;
            } else {
                size_t size = sizeof(*this);
                class_ro_t *ro = (class_ro_t *)memdup(this, size);
                return ro;
            }
        }
    };
    

    例:

    #import <Foundation/Foundation.h>
    
    @interface LGPerson : NSObject {
        int age;
    }
    @property (nonatomic, copy) NSString *name;
    - (void)sayHi;
    + (void)sayHello;
    @end
    
    @implementation LGPerson
    - (void)sayHi {
        
    }
    + (void)sayHello{
        
    }
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // NSObject *objc1 = [NSObject alloc];
            LGPerson *objc2 = [LGPerson alloc];
    
            NSLog(@"Hello, World!  %@",objc2);
        }
        return 0;
    }
    
    
    //控制台输出结果
    /*
    //获取元类  元类的方法列表
    (lldb) x/4gx LGPerson.class
    0x1000081f0: 0x00000001000081c8 0x0000000100350140
    0x100008200: 0x0000000100347430 0x0000802400000000
    (lldb) po 0x00000001000081c8
    LGPerson
    
    (lldb) p 0x00000001000081c8
    (long) $2 = 4295000520
    (lldb) p (class_data_bits_t*)($2+32)  //获取bits数据
    (class_data_bits_t *) $3 = 0x00000001000081e8
    (lldb) p (class_rw_t*) $3->data()
    (class_rw_t *) $4 = 0x000000010067abf0
    (lldb) p *$4
    (class_rw_t) $5 = {
      flags = 2684878849
      witness = 1
      ro_or_rw_ext = {
        std::__1::atomic<unsigned long> = {
          Value = 4295000120
        }
      }
      firstSubclass = nil
      nextSiblingClass = 0x00007fff850ffcd8
    }
    (lldb) p $5.ro_or_rw_ext
    (explicit_atomic<unsigned long>) $6 = {
      std::__1::atomic<unsigned long> = {
        Value = 4295000120
      }
    }
    (lldb) p $5.properties()
    (const property_array_t) $7 = {
      list_array_tt<property_t, property_list_t> = {
         = {
          list = 0x0000000000000000
          arrayAndFlag = 0
        }
      }
    }
    (lldb) p $7.list
    (property_list_t *const) $8 = 0x0000000000000000
    (lldb) p *$7
    error: <user expression 9>:1:1: indirection requires pointer operand ('const property_array_t' invalid)
    *$7
    ^~~
    (lldb) p *$8
    error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory
    (lldb) p $5.methods()
    (const method_array_t) $11 = {
      list_array_tt<method_t, method_list_t> = {
         = {
          list = 0x0000000100008080
          arrayAndFlag = 4295000192
        }
      }
    }
    (lldb) p $11.list
    (method_list_t *const) $12 = 0x0000000100008080
    (lldb) p *$12
    (method_list_t) $13 = {
      entsize_list_tt<method_t, method_list_t, 3> = {
        entsizeAndFlags = 26
        count = 1
        first = {
          name = "sayHello"
          types = 0x0000000100003f4e "v16@0:8"
          imp = 0x0000000100003d80 (KCObjc`+[LGPerson sayHello] at main.m:22)
        }
      }
    }
    (lldb) p $13.get(0)
    (method_t) $14 = {
      name = "sayHello"
      types = 0x0000000100003f4e "v16@0:8"
      imp = 0x0000000100003d80 (KCObjc`+[LGPerson sayHello] at main.m:22)
    }
    (lldb) p $13.get(1)
    Assertion failed: (i < count), function get, file /Users/xiaokai/Desktop/逻辑IOS/Logic iOS 底层大师班2期班/20200909--大师班第3节课--OC对象原理(下)/20200909-大师班第3天-OC对象下-资料/01--课堂代码/可编译objc源码/runtime/objc-runtime-new.h, line 438.
    error: Execution was interrupted, reason: signal SIGABRT.
    The process has been returned to the state before expression evaluation.
    
    //获取类 类的属性列表  类的方法列表
    (lldb) x/4gx objc2
    0x100676d60: 0x001d8001000081f5 0x0000000000000000
    0x100676d70: 0x0000000000000000 0x0000000000000000
    (lldb) po 0x001d8001000081f5
    8303516107964917
    
    (lldb) p 0x001d8001000081f5
    (long) $17 = 8303516107964917
    (lldb) p 8303516107964917 & 0x00007ffffffffff8ULL
    (unsigned long long) $18 = 4295000560
    (lldb) p 4295000560
    (long) $19 = 4295000560
    (lldb) po 4295000560
    LGPerson
    
    (lldb) p (class_data_bits_t*)($19+32)  //获取bits数据
    (class_data_bits_t *) $21 = 0x0000000100008210
    (lldb) p $21->data()
    (class_rw_t *) $22 = 0x000000010067ac10
    (lldb) p *$22
    (class_rw_t) $23 = {
      flags = 2148007936
      witness = 0
      ro_or_rw_ext = {
        std::__1::atomic<unsigned long> = {
          Value = 4295000224
        }
      }
      firstSubclass = nil
      nextSiblingClass = NSUUID
    }
    (lldb) p $23.properties()
    (const property_array_t) $24 = {
      list_array_tt<property_t, property_list_t> = {
         = {
          list = 0x0000000100008198
          arrayAndFlag = 4295000472
        }
      }
    }
    (lldb) p $24.list
    (property_list_t *const) $25 = 0x0000000100008198
    (lldb) p *$25
    (property_list_t) $26 = {
      entsize_list_tt<property_t, property_list_t, 0> = {
        entsizeAndFlags = 16
        count = 1
        first = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
      }
    }
    (lldb) p $26.get(0)
    (property_t) $27 = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
    (lldb) p $26.get(1)
    Assertion failed: (i < count), function get, file /Users/xiaokai/Desktop/逻辑IOS/Logic iOS 底层大师班2期班/20200909--大师班第3节课--OC对象原理(下)/20200909-大师班第3天-OC对象下-资料/01--课堂代码/可编译objc源码/runtime/objc-runtime-new.h, line 438.
    error: Execution was interrupted, reason: signal SIGABRT.
    The process has been returned to the state before expression evaluation.
    (lldb) p $23.methods()
    (const method_array_t) $28 = {
      list_array_tt<method_t, method_list_t> = {
         = {
          list = 0x00000001000080e8
          arrayAndFlag = 4295000296
        }
      }
    }
    (lldb) p $28.list
    (method_list_t *const) $29 = 0x00000001000080e8
    (lldb) p *$29
    (method_list_t) $30 = {
      entsize_list_tt<method_t, method_list_t, 3> = {
        entsizeAndFlags = 26
        count = 4
        first = {
          name = "sayHi"
          types = 0x0000000100003f4e "v16@0:8"
          imp = 0x0000000100003d90 (KCObjc`-[LGPerson sayHi] at main.m:19)
        }
      }
    }
    (lldb) p $30.get(0)
    (method_t) $31 = {
      name = "sayHi"
      types = 0x0000000100003f4e "v16@0:8"
      imp = 0x0000000100003d90 (KCObjc`-[LGPerson sayHi] at main.m:19)
    }
    (lldb) p $30.get(1)
    (method_t) $32 = {
      name = ".cxx_destruct"
      types = 0x0000000100003f4e "v16@0:8"
      imp = 0x0000000100003e00 (KCObjc`-[LGPerson .cxx_destruct] at main.m:18)
    }
    (lldb) p $30.get(2)
    (method_t) $33 = {
      name = "name"
      types = 0x0000000100003f64 "@16@0:8"
      imp = 0x0000000100003da0 (KCObjc`-[LGPerson name] at main.m:13)
    }
    (lldb) p $30.get(3)
    (method_t) $34 = {
      name = "setName:"
      types = 0x0000000100003f6c "v24@0:8@16"
      imp = 0x0000000100003dd0 (KCObjc`-[LGPerson setName:] at main.m:13)
    }
    (lldb) p $30.get(4)
    Assertion failed: (i < count), function get, file /Users/xiaokai/Desktop/逻辑IOS/Logic iOS 底层大师班2期班/20200909--大师班第3节课--OC对象原理(下)/20200909-大师班第3天-OC对象下-资料/01--课堂代码/可编译objc源码/runtime/objc-runtime-new.h, line 438.
    error: Execution was interrupted, reason: signal SIGABRT.
    The process has been returned to the state before expression evaluation.
    
    //获取类  类的成员列表
    (lldb) x/4gx objc2
    0x101105420: 0x001d8001000081f5 0x0000000000000000
    0x101105430: 0x0000000000000000 0x0000000000000000
    (lldb) p 0x001d8001000081f5
    (long) $1 = 8303516107964917
    (lldb) p 0x001d8001000081f5 & 0x00007ffffffffff8ULL
    (unsigned long long) $2 = 4295000560
    (lldb) p (class_data_bits_t *)($2+32)  //获取bits
    (class_data_bits_t *) $3 = 0x0000000100008210
    (lldb) p $3->data()
    (class_rw_t *) $4 = 0x0000000101105830
    (lldb) p *$4
    (class_rw_t) $5 = {
      flags = 2148007936
      witness = 0
      ro_or_rw_ext = {
        std::__1::atomic<unsigned long> = {
          Value = 4295000224
        }
      }
      firstSubclass = nil
      nextSiblingClass = NSUUID
    }
    (lldb) p $5.ro
    (const class_ro_t *) $6 = 0x00000001000080a0
      Fix-it applied, fixed expression was: 
        $5.ro()
    (lldb) p $5.ro()
    (const class_ro_t *) $7 = 0x00000001000080a0
    (lldb) p *$7
    (const class_ro_t) $8 = {
      flags = 388
      instanceStart = 8
      instanceSize = 24
      reserved = 0
      ivarLayout = 0x0000000100003f17 "\x11"
      name = 0x0000000100003f0e "LGPerson"
      baseMethodList = 0x00000001000080e8
      baseProtocols = 0x0000000000000000
      ivars = 0x0000000100008150
      weakIvarLayout = 0x0000000000000000
      baseProperties = 0x0000000100008198
      _swiftMetadataInitializer_NEVER_USE = {}
    }
    (lldb) p $8.ivars
    (const ivar_list_t *const) $9 = 0x0000000100008150
    (lldb) p *$9
    (const ivar_list_t) $10 = {
      entsize_list_tt<ivar_t, ivar_list_t, 0> = {
        entsizeAndFlags = 32
        count = 2
        first = {
          offset = 0x00000001000081b8
          name = 0x0000000100003f22 "age"
          type = 0x0000000100003f56 "i"
          alignment_raw = 2
          size = 4
        }
      }
    }
    (lldb) p $10.get(0)
    (ivar_t) $11 = {
      offset = 0x00000001000081b8
      name = 0x0000000100003f22 "age"
      type = 0x0000000100003f56 "i"
      alignment_raw = 2
      size = 4
    }
    (lldb) p $10.get(1)
    (ivar_t) $12 = {
      offset = 0x00000001000081c0
      name = 0x0000000100003f26 "_name"
      type = 0x0000000100003f58 "@\"NSString\""
      alignment_raw = 3
      size = 8
    }
    (lldb) p $10.get(2)
    Assertion failed: (i < count), function get
    */
    
    

    相关文章

      网友评论

          本文标题:OC类原理

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