本文为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;
}
利用lldb
的x/4gx
查看4个元素的虚拟内存去查看JDPerson
这个类的元素。因为这个JDPerson
是空的啊,里面什么属性都没写,所以看4个完全足够了。毕竟第一个就是isa
元素。
命令: x/4gx JDPerson.class
结果:
图1.png然后我们po
打印一下第一个元素isa
命令: po 0x00000001000080c8
结果:
图2.png结果发现JDPerson
的isa
指向了自己???并不是这样的,这个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
结果 :
很明显,person
和图1中JDPerson.class
的isa
指向是不一样的。
结论 :
这就证明了图2中po
出来的JDPerson
并不是JDPerson
类。
继续验证 :
lldb
中执行命令 : p/x 0x00000001000080c8 & 0x00007ffffffffff8
然后我们看一下这个$2
的地址,执行命令 : x/4gx $2
看看$2
的isa
指向,执行命令:po 0x000000010034c0f0
结果 :
图片.png指向了NSObject
。这里就可以证明了,刚才的JDPerson
是元类。
3. NSObject的isa指向
lldb
执行命令:x/4gx NSObject.class
拿到isa
的指向,继续用蒙版计算。
执行命令 : p/x 0x000000010034c0f0 & 0x00007ffffffffff8
查看NSObject
的isa
指向了谁。
执行命令 : po $5
结果还是NSObject
。
所以,NSObject
的isa
还是指向了NSObject
。
4. isa的一条探索路线
这个时候,应该就很好理解那张神图中的虚线部分,关于isa
的指向了吧。
注意,本节我们只看isa
的走向,类的继承在本节不作为重点探索,所以,
只看虚线的链接,先别看实线
神图 :
图片.pngisa的路径走向 :
对象--->类对象--->元类--->根元类--->根元类
网友评论