结构体 isa_t

在本章中,我们从NSObject的定义出发,了解了OC中类和对象所对应的数据结构objc_class和objc_object。关于NSObject,objc_class和objc_object三者之间的关系,我们可以用下面的图来更清晰的了解:



其实 isa_t 是一个定义得非常"奇怪"的结构体,在 ObjC 源代码中可以看到这样的定义:

#define ISA_MASK      0x00007ffffffffff8ULL

#define ISA_MAGIC_MASK  0x001f800000000001ULL

#define ISA_MAGIC_VALUE 0x001d800000000001ULL

#define RC_ONE   (1ULL<<56)

#define RC_HALF  (1ULL<<7)

union isa_t {

    isa_t() { }

    isa_t(uintptr_t value) : bits(value) { }

    Class cls;

    uintptr_t bits;

    struct {

        uintptr_t indexed           : 1;

        uintptr_t has_assoc         : 1;

        uintptr_t has_cxx_dtor      : 1;

        uintptr_t shiftcls          : 44;

        uintptr_t magic             : 6;

        uintptr_t weakly_referenced : 1;

        uintptr_t deallocating      : 1;

        uintptr_t has_sidetable_rc  : 1;

        uintptr_t extra_rc          : 8;

    };

};

这是在 __x86_64__ 上的实现,对于 iPhone5s 等架构为 __arm64__ 的设备上,具体结构体的实现和位数可能有些差别,不过这些字段都是存在的,可以看这里的arm64 上结构体的实现

在本篇文章中, 我们会以 __x86_64__ 为例进行分析,而不会对两种架构下由于不同的内存布局方式导致的差异进行分析。在我看来,这个细节不会影响对 isa 指针的理解,不过还是要知道的。

笔者对这个 isa_t 的实现声明顺序有一些更改,更方便分析和理解。


union isa_t {

    ...

};

isa_t 是一个 union 类型的结构体,对 union 不熟悉的读者可以看这个 stackoverflow 上的回答。也就是说其中的 isa_t、cls、 bits 还有结构体共用同一块地址空间。而 isa 总共会占据 64 位的内存空间(决定于其中的结构体)

struct {

   uintptr_t indexed           : 1;

   uintptr_t has_assoc         : 1;

   uintptr_t has_cxx_dtor      : 1;

   uintptr_t shiftcls          : 44;

   uintptr_t magic             : 6;

   uintptr_t weakly_referenced : 1;

   uintptr_t deallocating      : 1;

   uintptr_t has_sidetable_rc  : 1;

   uintptr_t extra_rc          : 8;

};


在 isa_t 中,我们还有一些没有介绍的其它 bits,在这个小结就简单介绍下这些 bits 的作用

has_assoc:对象含有或者曾经含有关联引用,没有关联引用的可以更快地释放内存

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

deallocating:对象正在释放内存

has_sidetable_rc:对象的引用计数太大了,存不下

extra_rc:对象的引用计数超过 1,会存在这个这个里面,如果引用计数为 10,extra_rc 的值就为 9



从 NSObject 的初始化了解 isa

https://blog.csdn.net/fishmai/article/details/71158083

推荐阅读更多精彩内容