美文网首页iOS技术资料iOS 技术
iOS底层原理之六:isa指针实现之ISA_MASK

iOS底层原理之六:isa指针实现之ISA_MASK

作者: 估唔到 | 来源:发表于2018-10-01 23:48 被阅读32次

    题记

    前面我们提到,在OC对象中实例对象的isa是指向类对象,类对象的isa指向元类对象,这样我们可以通过isa把OC中的三种对象联系起来。那么,isa是怎么实现的呢?实例对象的isa直接存放着类对象的地址,类对象的isa直接存放元类对象的地址吗?


    准备工作

    • 首先老规矩我们准备一个JJPerson继承自NSObject,分别拿到它的实例对象,类对象和元类对象,并分别打印它们的地址值
    • 我们先通过打印拿到person的isa地址和person的类对象地址,通过对比我们发现,其实他们是并不相等的
    • person->isa:0x001d8001000011d1
    • personClass:0x00000001000011d0

    那么实例对象是怎么通过isa来找到类对象的呢?这里就不得不提一个ISA_MASK的东西,我们还是从源码寻找答案。


    分析


    • 其实从64bit开始,isa需要进行一次位运算,才能计算出真实地址,这个位运算的对象就是ISA_MASK
    • ISA_MASK的值不是唯一的,在arm64和X86架构下是不同的



      有了ISA_MASK后我们可以看到看到,person的isa通过和ISA_MASK进行一次位运算后,得出的值就是我们JJPerson类对象在内存中的值。同理类对象和元类对象我们也可以去证明。不过我们直接尝试去获取类对象的isa时,会发现并不能直接获取到,因为Xcode提示说它并不认为这是一个结构体



      但是我们点击Class进去,再点击进入它的objc_class里面可以看到,它是确实存在isa的,但是只是没有暴露给我们而已

    其实这个问题不难解决,因为我们可以看到objc_class的结构,那么我们可以定义一个和它一样的结构体来获取isa

    • 为了避免明明冲突,我们定义一个jj_objc_class结构体,和objc_class一样,它里面也有一个Class类型的isa
    • 在30行代码处,我们通过自定义的结构体去获取JJPerson的类对象
    • 通过打印我们可以发现,我们新获取JJPerson的类对象isa通过和ISA_MASK进行位运算后,得出的地址正是我们JJPerson元类对象的地址



      这也证明了,我们OC对象中的isa并不是直接存放所指向对象的地址值,而是需要通过和ISA_MASK进行一次位运算才能得出真实地址。但是为什么苹果要使用这种做法呢?我们后面再来分析。

    相关文章

      网友评论

        本文标题:iOS底层原理之六:isa指针实现之ISA_MASK

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