iOS开发 类的原理分析

170 阅读2分钟

前言

之前我们知道将实例对象的isa地址和掩码MASK做位运算便可以获得类的地址,接下来我们便要分析类的结构。

image.png

Objc源码中的类结构

image.png 其实objc_class内部有非常多行代码,但是真正影响objc_class内存的只有成员变量,也就是图中红框所示的四个成员变量,为什么要注释Class ISA;呢?因为objc_class继承自objc_object,而objc_object内部已经有了ISA成员变量。

cache_t占多大内存?

我们首先跳过cache分析这个bits存储了什么东西,也就要拿到bits的内存地址,我们已经有了class的地址,并且知道了ISA和superclass两个成员变量都分别占8个字节,那么问题就是cache占多大内存呢?让我们进入cache_t的源码。

进入cache_t内部后会发现也是十分冗长的一段代码,但其实真正占内存的就这么几个成员变量。

image.png

  • _bucketsAndMaybeMask: explicit_atomic是泛型,所以大小取决于uintptr_t,也就是8个字节
  • 下面是个联合体,联合体中分别是一个结构体和一个_originalPreoptCache,由联合体的性质可知,内部同时只有一个变量占内存。
  • 结构体:_maybeMask的大小由mask_t决定,进入mask_t内部可知mask_t就是个uint32_t,即占4个字节,_flags和_occupied各占2个字节,共8个字节。
  • _originalPreoptCache: 同样是泛型,preopt_cache_t *明显是个结构体指针对象,即8字节。 总结:cache_t共占16字节。

bits的内存地址

所以ISA+superclass+cache所占的内存大小为8+8+16=32,我们只需要在class的地址(0x100008380)加上32个字节就能获得bits的内存地址,即(0x1000083a0)

层层递进

有了bits的内存地址后,我们层层递进获取LGPerson这个类的属性及实例方法。

image.png LGPerson类结构图

image.png

image.png

image.png

isa的走位链

image.png

元类也有继承链

image.png

指针类型

普通指针

对象指针

数组指针

内存平移

uintptr_t 8字节