isa的初始化和指向分析

332 阅读4分钟

isa的初始化和指向分析

在探索对象alloc初始化的过程中,会不可避免的接触到isa的初始化,那么isa是什么呢?从苹果的文档描述来看,A pointer to the class definition of which this object is an instance,isa其实是指一个实例对象指向该对象的类的指针,是不是指针我们先保留疑问,我们通过源码来查看它的结构:

从源码可以看出isa其实是个联合体,什么是联合体,什么是位域,这里不做介绍,下面介绍一下ISA_BITFIELD位域里面一些参数的定义:

nonpointer:表示是否对isa开启指针优化 。0代表是纯isa指针,1代表除了地址外,还包含了类的一些信息、对象的引用计数等。

has_assoc:关联对象标志位

has_cxx_dtor:该对象是否有C++或Objc的析构器,如果有析构函数,则需要做一些析构的逻辑处理,如果没有,则可以更快的释放对象

shiftcls:存在类指针的值,开启指针优化的情况下,arm64位中有33位来存储类的指针

magic:判断当前对象是真的对象还是一段没有初始化的空间

weakly_referenced:是否被指向或者曾经指向一个ARC的弱变量,没有弱引用的对象释放的更快

deallocating:是否正在释放

has_sidetable_rc:当对象引用计数大于10时,则需要进位

extra_rc:表示该对象的引用计数值,实际上是引用计数减一。例如:如果引用计数为10,那么extra_rc为9。如果引用计数大于10,则需要使用has_sidetable_rc(散列表暂不做介绍)

第一个参数表示是否对isa指针进行了优化,如果没有优化,则使用的就是类指针,如果优化则会存储一些其他的信息,这时候代表的就不是一个指针,所以通过这里我们简单的介绍了解了isa是什么,以下是来自源码的截图:

光看图很懵逼,我们通过代码来一步一步的试着分析上面图的流程,

object_getClass通过传入对象返回对应的类,通过上面的图我们可以得出其实这个方法是用过isa存储的类指针获取对应的类,

// Define SUPPORT_INDEXED_ISA=1 on platforms that store the class in the isa

// field as an index into a class table.

#if SUPPORT_INDEXED_ISA 表示 isa_t 中存放的 Class 信息是 Class 的地址,还是一个索引(根据该索引可在类信息表中查找该类结构地址)。根据宏定义的判断条件,我们这应该是return (Class)(isa.bits & ISA_MASK);,对isa.bits进行掩码计算,得到对应类的内存地址,来,代码走一波~

我们通过打印内存地址可以发现,x/4xg打印对象t的第一个属性内存地址是isa的地址,通过isa.bits & ISA_MASK得到的内存地址和打印Test类地址一致, 这就证明了isa_t中存放了class类的内存地址,对象就是这么关联到类,从另外一种方法也可以证明, newisa.shiftcls = (uintptr_t)cls >> 3; 位域内参数为shiftcls的位空间存放的是类指针的内存地址,那么我们可以对isa的内存地址进行>>3<<3,<<17>>17,得到类指针的内存地址,然后打印Test类地址进行比较,此时会发现两者的地址也是一致的。

接下来我们来看一张网上传的很广的有关于isa指针指向的图,

可以清晰的看出isa的指向: 对象->类->元类->根元类->根元类(自己) 简单的来做个测试吧~

通过不断的进行掩码计算获取isa的指向,最后指向根元类自己NSObject达到闭环,印证了上面的那副isa走向图。可能有些同学不懂LLDB指令,可以自行查找下相关的资料,这里就不多做论诉。

最后来一张isa初始化的流程图:

==============================================

PS:欢迎留言探讨交流,目的纯粹为了学习进步。