iOS爱上底层-isa初始化&指向

453 阅读3分钟

什么是isa?

每个对象都是从NSObject类继承的isa实例变量来连接到运行时系统。 它指向从类定义编译的结构。 通过isa,对象可以找到运行时所需的任何信息,例如其在继承层次结构中的位置,其实例变量的大小和结构以及可以响应消息执行的方法实现的位置。

isa的结构

从图片中我们可以得到以下几个信息:
1、isa就是isa_t,且isa是个联合体位域。
2、isa_t() { }:单纯的初始化
3、isa_t(uintptr_t value) : bits(value) { }:也是单纯的初始化,只不过这个有传值,和2相同
4、Class cls:绑定关联一个class(其实就是class和isa绑定在一起)
5、bits:决定联合体的长度,并且对位域ISA_BITFIELD(bits和上面的cls是互斥的,赋值了cls就不出创建bits)
6、ISA_BITFIELD:结构如下
arm64:
x86_64:
参数详解 :
nonpointer:表示是否对 isa 指针开启指针优化 0:纯isa指针,1:不止是类对象地址,isa 中包含了类信息、对象的引用计数等。

has_assoc:关联对象标志位,0没有,1存在。

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

shiftcls: 存储类指针的值。开启指针优化的情况下,在arm64架构中有33位用来存储类指针,x86_64则用44位存储。

magic:用于调试器判断当前对象是真的对象还是没有初始化的空间

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

deallocating:标志对象是否正在释放内存

has_sidetable_rc:当对象引用技术大于 10 时,则需要借用该变量存储进位

extra_rc:当表示该对象的引用计数值,实际上是引用计数值减 1, 例如,如果对象的引用计数为 10,那么 extra_rc 为 9。如果引用计数大于 10, 则需要使用到下面的 has_sidetable_rc。

isa的初始化

我们通过initIsa进入到初始化isa的详细代码中看看。

根据流程,我们会发现nonpointer一般为true,所以他一般都是走else分支内容。而else的内容,就是在isa初始化的时候,将类的信息关联到isa。其中最重要的则是shiftcls。因为shiftcls代表类的结构,接下来我们就来证明isa关联类的信息。

1、p/x Person.class:首先我们先打印出class的16进制地址。
2、x/4xg per:然后我们打印出per的地址信息,第一个地址必然是isa。
3、p/x 0x001d800100001129 & 0x00007ffffffffff8:我们用isa的地址&掩码,就得到了我们第一行的地址。由此可见,isa&掩码之后就和类关联起来了。

元类

首先我们要明白一个叫元类的类:它是由系统在创建一个类的时候,为了在后期的便捷,就会创建一个叫元类的类。既元类就是类对象所属的类(元类的定义和创建都是编译器自动完成的,无需人为干涉)。

isa的指向

从图片中可以得出结论: 对象的isa指向类对象,类对象的isa指向元类,元类的isa指向根源类,并且NSObject的isa也是指向根源类(根源类就是NSObject的元类)。并附上经典的isa走位图。