第三节—isa的指向分析

本文为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的指向分析)