底层原理 类的本质
复习一下IOS 底层原理 对象的本质–(1),可以看出来实例对象实际是上结构体,那么这个结构体是有类指针和成员变量组成的。
1 | //Person |
经过xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main64.cpp编译之后其实Person对象是:
1 | struct Person_IMPL { |
NSObject_IMPL结构体:
1 | struct NSObject_IMPL { |
那么NSObject在内存中包括
isa指针- 其他成员变量

isa地址就是instance的地址,其他成员变量排在后边,也就是instance的地址就是isa的地址。
那么这个isa指向的到底是什么呢?
请往下继续看:
先看下这段代码:
1 | NSObject *ob1=[[NSObject alloc]init]; |
这代码是输出了几个NSObject的对象的类和NSObject的类对象的地址,可以看到cl1==cl2、cl3==cl4==cl5。
Class的本质
我们知道不管是类对象还是元类对象,类型都是Class,class和mete-class的底层都是objc_class结构体的指针,内存中就是结构体。
1 | Class objectClass = [NSObject class]; |
点击class来到内部,可以发现
1 | typedef struct objc_class *Class; |
class对象其实是指向objc_class的结构体,因此我们可以说类对象或元类对象在内存中其实就是objc_class结构体。
来到objc_class内部,在源码中经常看到这段源码
1 | struct objc_class { |
这段代码明显是 已经OBJC2_UNAVAILABLE,说明代码已经不在使用了。那么objc_class结构体内部结构到底是什么呢?通过objc搜寻runtime的内容可以看到objc_class内部
1 | struct objc_class : objc_object { |
我们发现这个结构体继承 objc_object 并且结构体内有一些函数,因为这是c++结构体,在c上做了扩展,因此结构体中可以包含函数。我们来到objc_object内,截取部分代码
1 | struct objc_object { |
那么我们之前了解到的,类中存储的类的成员变量信息,方法列表,协议列表,截取class_rw_t内部实现代码
1 | struct class_rw_t { |
而class_rw_t是通过bits.data()获取的,截取bits.data()查看内部实现,而仅仅是bits&FAST_DATA_MASK。
1 | class_rw_t* data() { |
而成员变量则是存储在class_ro_t内部中的,我们来到class_ro_t内部查看:
1 | struct class_ro_t { |
最后通过一张图总结一下:

那么我们来证明一下:
我们可以自定义一下一个和系统一样的结构体,那么我们当我们强制转化的时候,他们赋值会一一对应,此时我们就可以拿到结构体的内部的值。
下边代码是我们自定义的值:
1 | // |
这段代码亲测可用,直接复制自己新建.h文件导入’main.m’即可,将main.m改成main.mm或者将其他某一个.m改成.mm运行就可以运行了。
那么我们再拿出来经典的那张图挨着分析isa 和superclass的指向

instance 对象验证
使用 p/x输出obj16进制的地址,然后isa指针需要经过一次 & ISA_MASK操作之后才得到真正的地址。实施之后:
1 | //object |
从面的输出结果中我们可以发现instance对象中确实存储了isa指针和其成员变量,同时将instance对象的isa指针经过&运算之后计算出的地址确实是其相应类对象的内存地址。由此我们证明isa,superclass指向图中的1,2,3号线。
class 对象验证
接着我们来看class对象,同样通过上一篇文章,我们明确class对象中存储着isa指针,superclass指针,以及类的属性信息,类的成员变量信息,类的对象方法,和类的协议信息,而通过上面对object源码的分析,我们知道这些信息存储在class对象的class_rw_t中,我们通过强制转化来窥探其中的内容
1 | //objectClass and objectMetaClass |
有此结果得知objectMetaClass==objectClass->isa==0x00007fff8e3ba0f0,personClass->isa==personMetaClass==0x0000000100002440,studentClass->isa==studentMetaClass==0x0000000100002490。
由此我们证明isa,superclass指向图中,isa指针的4,5,6号线,以及superclass指针的7,8,9号线。
meta-class对象验证
最后我们来看meta-class元类对象,上文提到meta-class中存储着isa指针,superclass指针,以及类的类方法信息。同时我们知道meta-class元类对象与class类对象,具有相同的结构,只不过存储的信息不同,并且元类对象的isa指针指向基类的元类对象,基类的元类对象的isa指针指向自己。元类对象的superclass指针指向其父类的元类对象,基类的元类对象的superclass指针指向其类对象。
与class对象相同,我们同样通过模拟对person元类对象调用.data函数,即对bits进行&FAST_DATA_MASK(0x00007ffffffffff8UL)运算,并转化为class_rw_t。
1 | // objectMetaClass->superclass = 0x00007fff8e3ba140 NSObject |
由上面可以看出,studentMetaClass->isa,personMetaClass->isa,objectMetaClass->isa结果mask之后都是0x00007fff8e3ba0f0,与p/x objectMetaClass结果一致,则验证了13,14,15号线,studentMetaClass->superclass =0x0000000100002440,personMetaClass = 0x0000000100002440验证12号线,personMetaClass->isa=0x00007fff8e3ba0f0和objectMetaClass = 0x00007fff8e3ba0f0验证了11号线,objectMetaClass->superclass = 0x00007fff8e3ba140 NSObject验证10号线。
总结:
对象的isa指向哪里?
- instance对象的isa指向class对象
- class对象的isa指向meta-class对象
- meta-class对象的isa指向基类的meta-class对象
- class和meta-class的内存结构一样的,只是值不一样
OC的类信息存放在哪里?
- 对象方法、属性、成员变量、协议信息存放在class对象中
- 类方法存放在meta-class对象中
- 成员变量具体值存放在instance对象中
资料下载
- 学习资料下载
- demo code
最怕一生碌碌无为,还安慰自己平凡可贵。
本文章之所以图片比较少,我觉得还是跟着代码敲一遍,印象比较深刻。

/