最近想重新充下电, 巩固下基础, 把以前学过的东西再重新整理一遍, 我是搬运工, 懂得都懂
-
在arm64架构之前,isa就是一个普通的指针,存储着Class、Meta-Class对象的内存地址
-
从arm64架构开始,对isa进行了优化: 变成了一个共用体(union)结构,还使用位域来存储更多的信息, 共用体中的变量都公共一块内存
union isa_t
{
Class cls;
uintptr_t bits;
// 该结构体只是为了增加可读性
// 一共64位
struct {
uintptr_t nonpointer : 1; // 占1位
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 33; // 占33位
uintptr_t magic : 6; // 占6位
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 19; // 占19位
}
};
isa中存储的信息
isa64情况.jpeg名称 | 用途 |
---|---|
nonpointer | 0:代表普通的指针,存储着Class、Meta-Class对象的内存地址 1:代表优化过,使用位域存储更多的信息 |
has_assoc | 是否有设置过关联对象,如果没有,释放时会更快 |
has_cxx_dtor | 是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快 |
shiftcls | 存储着Class、Meta-Class对象的内存地址信息 |
magic | 用于在调试时分辨对象是否未完成初始化 |
weakly_referenced | 是否有被弱引用指向过(指向过,不是正在指向),如果没有,释放时会更快 |
deallocating | 对象是否正在释放 |
extra_rc | 里面存储的值是引用计数器减1 |
has_sidetable_rc | 引用计数器是否过大无法存储在isa中 如果为1,那么引用计数会存储在一个叫SideTable的类的属性中 |
以实例对象通过isa查找类对象的过程为例子
得到实例对象的isa共用体中的shiftcls中的数据, 然后通过 (& ISA_MASK) 的位运算 得到 类/元类对象的地址值
ps: 类和元类对象的地址值后三位 一定是000, 这是由 ISA_MASK决定的
经典流程图
WechatIMG115.jpeg总结
-
instance的isa指向class
-
class的isa指向meta-class
-
meta-class的isa指向基类的meta-class
-
class的superclass指向父类的class
-
如果没有父类,superclass指针为nil
-
meta-class的superclass指向父类的meta-class
-
基类的meta-class的superclass指向基类的class
-
instance调用对象方法的轨迹
-
isa找到class,方法不存在,就通过superclass找父类
-
class调用类方法的轨迹
-
isa找meta-class,方法不存在,就通过superclass找父类
如果找不到 会报 unrecognized selector sent to instance .... 的错误
arm64之后 isa不会直接指向 class 或者 meta-class, 而是经过一次位运算得到的
网友评论