美文网首页
系统底层源码分析(14)——isa

系统底层源码分析(14)——isa

作者: 无悔zero | 来源:发表于2021-06-19 14:31 被阅读0次
    • 联合体

    前面提到isa关联了类,那么isa是什么?isa的本质是联合体:

    union isa_t {//联合体
        isa_t() { }
        isa_t(uintptr_t value) : bits(value) { }
    
        Class cls;
        uintptr_t bits;
    #if defined(ISA_BITFIELD)
        struct {//位域
            ISA_BITFIELD;  // defined in isa.h
        };
    #endif
    };
    
    • 关联

    它是怎么关联类的,比如Person继承NSObjectPerson就需要关联到NSObject,靠的就是isaisa是默认属性:

    @interface NSObject <NSObject> {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wobjc-interface-ivars"
        Class isa  OBJC_ISA_AVAILABILITY;
    #pragma clang diagnostic pop
    }
    
    • 指向图
    1. 一般对象内存结构中的第一个属性就是isaisa指向该类对象(Class本身也是一个对象),而类对象指元类,元类最终指向根元类,根元类又循环指向自己。

    2. isa:对象 -> 类 -> 元类 -> 根元类 <-> 根元类

    3. 继承关系:子类 -> 父类 -> NSObject -> nil

    4. 根元类继承NSObject

    • 验证

    可以用代码验证:

    void test(){
        // 实例对象
        Person *p = [Person alloc];
        // 类
        Class class = object_getClass(p);
        // 元类
        Class metaClass = object_getClass(class);
        // 根元类
        Class rootMetaClass = object_getClass(metaClass);
        // 根根元类
        Class rootRootMetaClass = object_getClass(rootMetaClass);
        NSLog(@"\n%p 实例对象\n%p 类\n%p 元类\n%p 根元类\n%p 根根元类",object1,class,metaClass,rootMetaClass,rootRootMetaClass);
    }
    
    //打印结果
    0x100406b10 实例对象
    0x100008100 类
    0x1000080d8 元类
    0x7fff98b700f0 根元类
    0x7fff98b700f0 根根元类
    (lldb) po 0x100406b10
    <Person: 0x100406b10>
    
    (lldb) po 0x100008100
    Person
    
    (lldb) po 0x1000080d8
    Person
    
    (lldb) po 0x7fff98b700f0
    NSObject
    
    (lldb) po 0x7fff98b700f0
    NSObject
    
    
    //打印实例对象内存结构
    (lldb) x/4gx 0x100406b10  
    0x100406b10: 0x001d800100008101 0x0000000000000000
    0x100406b20: 0x00007fff916aa028 0x00007fff7da3ce28
    //打印首地址的值
    (lldb) po 0x100406b10    
    <Person: 0x100406b10>
    //打印内存结构里第一个值
    (lldb) p/x 0x001d800100008101 & 0x00007ffffffffff8  //转换
    (long) $4 = 0x0000000100008100
    (lldb) po 0x0000000100008100
    Person
    
    
    //打印Person类内存结构
    (lldb) x/4gx 0x100008100
    0x100008100: 0x00000001000080d8 0x00007fff98b70118
    0x100008110: 0x0000000100464f10 0x000780100000000f
    //打印Person的isa
    (lldb) po 0x00000001000080d8
    Person
    //打印Person父类
    (lldb) po 0x00007fff98b70118
    NSObject
    //打印NSObject类内存结构
    (lldb) x/4gx 0x00007fff98b70118
    0x7fff98b70118: 0x00007fff98b700f0 0x0000000000000000
    0x7fff98b70128: 0x000000010054ebe0 0x0002801000000003
    //打印NSObject的isa,和上面打印Person父类不一样
    (lldb) po 0x00007fff98b700f0
    NSObject
    //打印NSObject父类
    (lldb) po 0x0000000000000000
    <nil>
    
    
    //打印根元类内存结构
    (lldb) x/4gx 0x7fff98b700f0
    0x7fff98b700f0: 0x00007fff98b700f0 0x00007fff98b70118
    0x7fff98b70100: 0x000000010054ee10 0x0004e03100000007
    //打印根元类的isa,指向自己
    (lldb) po 0x00007fff98b700f0
    NSObject
    //打印根元类的父类
    (lldb) po 0x00007fff98b70118
    NSObject
    
    #   define ISA_MASK        0x00007ffffffffff8ULL
    
    • 源码

    我们从objc4-750源码探究object_getClass

    Class object_getClass(id obj)
    {
        if (obj) return obj->getIsa();
        else return Nil;
    }
    
    inline Class 
    objc_object::getIsa() 
    {
        if (!isTaggedPointer()) return ISA();
        ...
    }
    
    inline Class 
    objc_object::ISA() 
    {
        assert(!isTaggedPointer()); 
    #if SUPPORT_INDEXED_ISA
        if (isa.nonpointer) {
            uintptr_t slot = isa.indexcls;
            return classForIndex((unsigned)slot);
        }
        return (Class)isa.bits;
    #else
        return (Class)(isa.bits & ISA_MASK);//最终得到isa指向的类在对象内存中的值
    #endif
    }
    

    object_getClass底层就是通过isa得到该对象的类,所以isa指向对象的类。

    相关文章

      网友评论

          本文标题:系统底层源码分析(14)——isa

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