美文网首页
第三节—isa的指向分析

第三节—isa的指向分析

作者: L_Ares | 来源:发表于2020-10-21 14:50 被阅读0次

    本文为L_Ares个人写作,包括图片皆为个人亲自操作,以任何形式转载请表明原文出处。

    前面的几节基本上已经初步的了解了isa的类型,isa的初始化,isa做了什么。但是全部都是基于对象的,对象中的isa是继承与类的isa,并且指向了类,从而绑定了对象与类,阐述了对象与类的关系。

    那么本节换个角度,从基于类,来专门看一下isa一路指向了哪里,看一下isa的一路历程。

    本节还是要用到objc781版本的源码的,因为这一切,全都基于在objc781版本源码的探索。

    isa探索类和元类

    1. 类的isa指向

    还是那个项目,我们利用lldb来看一下,一个JDPerson类的isa指向了谁。在main.m中,随便alloc一个JDPerson对象,挂上断点,进入lldb调试。

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            
            //0x00007ffffffffff8
            JDPerson *person = [JDPerson alloc];
            
            NSLog(@"Hello, World!");      //挂上断点
            
        }
        return 0;
    }
    
    

    利用lldbx/4gx查看4个元素的虚拟内存去查看JDPerson这个类的元素。因为这个JDPerson是空的啊,里面什么属性都没写,所以看4个完全足够了。毕竟第一个就是isa元素。

    命令: x/4gx JDPerson.class

    结果:

    图1.png

    然后我们po打印一下第一个元素isa

    命令: po 0x00000001000080c8

    结果:

    图2.png

    结果发现JDPersonisa指向了自己???并不是这样的,这个isa指向的地址上存储的是元类(meta Class)

    于是,我们可以根据这些和前两节的内容,根据isa的指向,得到了这样的一条线。

    对象(类实例化的表现)--->类(元类实例化)--->元类

    这里,

    • 对象 : 是我们可以利用类进行实例化出来的。
    • 类 : 我们可以写出来的,可以用的,但是一个类的内存只有一份,不信你可以随意把一个类利用各种方式alloc,然后lldb或者挂断点看他的内存地址。并且,类不是我们创建的,而是系统创建的。
    • 元类 : 系统编译的时候产生的,同时创建了编译器和方法。

    2. 证明po出来的对象是元类

    问 : 怎么证明这次po打印出来的JDPerson是元类不是类?

    思路 :

    还记得object_getClass吗?那我们根据object_getClass返回类型的源码来看,最终是通过return (Class)(isa.bits & ISA_MASK);这句代码返回的类型Class吧。

    那就给刚才po打印出来的isa 与位运算上ISA_MASK,来看看object_getClass到底返回的是不是JDPerson自己,还是JDPerson元类。

    判断依据 :

    一样的地址的话,因为类的内存只有一份,那肯定就是自己,如果地址不一样,那必然不是自己。

    已知条件 :

    x86_64下的ISA_MASK = 0x00007ffffffffff8

    验证 :

    lldb中执行命令 : x/4gx person

    看一下JDPerson类的地址,执行命令 : x/4gx person

    图3.png

    结果 :

    很明显,person和图1中JDPerson.classisa指向是不一样的。

    结论 :

    这就证明了图2中po出来的JDPerson并不是JDPerson类。

    继续验证 :

    lldb中执行命令 : p/x 0x00000001000080c8 & 0x00007ffffffffff8

    图4.png

    然后我们看一下这个$2的地址,执行命令 : x/4gx $2

    图5.png

    看看$2isa指向,执行命令:po 0x000000010034c0f0

    结果 :

    图片.png

    指向了NSObject。这里就可以证明了,刚才的JDPerson是元类。

    3. NSObject的isa指向

    lldb执行命令:x/4gx NSObject.class

    图片.png

    拿到isa的指向,继续用蒙版计算。

    执行命令 : p/x 0x000000010034c0f0 & 0x00007ffffffffff8

    图片.png

    查看NSObjectisa指向了谁。

    执行命令 : po $5

    图片.png

    结果还是NSObject

    所以,NSObjectisa还是指向了NSObject

    4. isa的一条探索路线

    这个时候,应该就很好理解那张神图中的虚线部分,关于isa的指向了吧。

    注意,本节我们只看isa的走向,类的继承在本节不作为重点探索,所以,

    只看虚线的链接,先别看实线

    神图 :

    图片.png

    isa的路径走向 :

    对象--->类对象--->元类--->根元类--->根元类

    相关文章

      网友评论

          本文标题:第三节—isa的指向分析

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