isa 分析:
每个对象在初始化的时候都会生成一个isa ,且继承于NSObject的类的第一个属性都是isa ;

alloc初始化isa流程
以GGPerson *person = [GGPerson alloc]; 为例
isa 的初始化: alloc->_objc_rootAlloc->callAlloc->initInstanceIsa->initIsa
isa 是类和对象之间的关联
声明一个对象,底部显示这是大家最常见的一个画面

下面我们来分析一下isa是如何关联类和对象的
object_getClass(object); 通过一个对象来获取当前类这句代码大家都很熟悉,那么他是怎么通过一个对象获取一个类的哪?一块看下底层代码
object_getClass
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
直接就看到 obj->getIsa(),是不是很神奇, 接着走
objc_object::getIsa()
{
if (!isTaggedPointer()) return ISA();
} 备注:这段代码只展示了必要的部分
ISA()到底怎么得到的当前类,我们接着走
objc_object::ISA()
{assert(!isTaggedPointer());
#if SUPPORT_INDEXED_ISA ->0,永远不成立
if (isa.nonpointer) {
uintptr_t slot = isa.indexcls;
return classForIndex((unsigned)slot);
}
return (Class)isa.bits;
#else
return (Class)(isa.bits & ISA_MASK); ->重点
#endif
}
(Class)(isa.bits & ISA_MASK) 这句代码我们拿到了当前类
ISA_MASK 这个玩意什么鬼,为什么要 & ISA_MASK ?
# define ISA_MASK 0x00007ffffffffff8ULL 这个是ISA_MASK的定义,这块的存在是个掩码,相当于一个面具,通过它是相当于把想展示的东西给展示出来
下面我们来通过代码具体来展示一下 isa 与 类 的具体值打印,是不是很吸引眼球

isa 自身分析:
isa自身为64位,它的自身每一位都是有讲究的,我们来看一下isa的结构
0->7 : nonpointer:表示是否对isa指针开启指针优化 0:纯isa指针, 1:不止是类对象地址,isa中包含了类信息 对象的引用计数等
has_assoc:关联对象标志位,0没有,1存在
has_cxx_dtor:该对象是否有c++或者objc的析构器,如果有析构函数,则需要做析构逻辑,如果没有,则可以更快的释放对象
8->24: shiftcls:存储类指针的值,开启指针优化的情况下,在arm64架构中有33位用来存储类指针
32->40 magic:用于调试器判断当前对象是真的对象还是没有初始化控件
weakly_referenced:指对象是否被指向或者曾经指向一个ARC的弱变量,没有弱引用的对象可以更快释放
deallocating: 标志对象是否正在释放内存
has_sidetable_rc:当对象引用计数大于10时,则需要借用该变量储存进位
48->57 extra_rc: 当表示该对象的引用计数值,实际上是引用计数值减1,例如,如果对象的引用计数为10,那么extra_rc为9,如果引用计数大于10,则需要使用到下面的has_sidetable_rc.
isa的指向
首先我们应该清楚对象是我们根据类实例化得来
类是代码写出来的并且内存只有一份,是系统产生
元类是系统编译来的,当系统发现有这么一个类,系统根据这个类方便操作同时创建了元类,这些是编译期执行的
他们的指向关系是这样的
对象->类对象->元类-> 根元类->根元类类
NSObject 为基类,所有对象都继承于它 ,它的指向为根源类

很多人应该都看过这幅图,这幅图应该是实线superclass 和 isa分开来看
superclass为继承关系 例如上面的LGPerson和NSObject的关系,NSObject继承nil
isa为指向关系 即对象的isa指向类,类的isa指向根源类,根源类的isa指向根源类自己
That's all!