从 isa 到 cache,从方法列表到属性列表
一次把「一个 Class 里到底装了什么」讲清楚
在 Runtime 视角下,Objective-C 的 Class 并不是一个抽象概念,
而是一块结构严谨、职责清晰的内存结构。
本文将围绕 Class 的真实组成,系统讲解:
- isa 指针到底指向哪
- cache 为什么决定性能
- 方法列表、属性列表、协议列表各自干什么
- 一个类里,除了方法,还存了哪些东西
一、先给结论:一个 Class 里有什么?
从 Runtime 角度,一个类(Class)至少包含以下几大部分:
Class
├─ isa
├─ superclass
├─ cache
├─ method list
├─ property list
├─ protocol list
├─ ivar list
├─ class_rw_t / class_ro_t
└─ 元类(Meta Class)
下面我们逐一展开。
二、isa —— 类的“身份指针”
1. isa 是什么
- isa 是一个指针
- 对象的 isa → Class
- 类的 isa → Meta Class
instance ──isa──▶ Class ──isa──▶ Meta Class
在 arm64 以后:
-
isa 是 非纯指针(non-pointer isa)
-
高位存储了:
-
引用计数信息
-
weak 标志
-
是否有关联对象
-
但 逻辑语义没有变化。
三、cache —— 方法调用的性能核心
1. cache 是什么
- cache 是一个 SEL → IMP 的映射表
- 存在于 Class 中
- 用于加速方法查找
cache
├─ bucket[SEL → IMP]
└─ mask / occupied
2. cache 在方法查找中的位置
objc_msgSend 查找顺序:
1️⃣ cache
2️⃣ method list
3️⃣ superclass → 重复 1、2
cache 永远是第一站。
3. cache 的填充时机
-
cache 是 懒加载 的
-
第一次方法调用:
-
cache 未命中
-
method list 找到 IMP
-
写入 cache
-
之后同一个 SEL:
直接命中 cache
4. cache 为什么不区分类?
cache 的 key 是:
SEL
但 cache 属于 某一个 Class。
因此:
A.foo → A 的 cache
B.foo → B 的 cache
即使 SEL 相同,也互不干扰。
四、method list —— 方法的“原始数据源”
1. method list 是什么
- method list 是一个数组
- 每一项是一个 method_t
method_t
├─ SEL name
├─ IMP imp
└─ const char *types
也就是我们熟悉的三要素:
SEL + IMP + Type Encoding
2. method list 的来源
method list 由以下部分合并而来:
-
类本身实现的方法
-
Category 中的方法
⚠️ Category 的方法:
- 会 后加载、前插入
- 因此可以覆盖原方法
五、property list —— 属性的声明信息
1. property list 是什么
- 属性列表存的是 声明信息
- 不是 ivar
- 不是 getter / setter 的实现
objc_property_t
├─ name
└─ attributes (copy, nonatomic, strong ...)
2. property list 干什么用
-
Runtime 反射
-
KVC / KVO
-
自动序列化 / ORM
但注意:
方法调用完全不依赖 property list
六、ivar list —— 实例变量的真实布局
1. ivar list 是什么
-
ivar list 描述的是:
- 成员变量
- 内存偏移
- 类型
ivar_t
├─ name
├─ type
└─ offset
2. ivar list 与对象内存
instance memory
├─ isa
├─ ivar1
├─ ivar2
- ivar list 决定对象内存布局
- 子类 ivar 会追加在父类之后
七、protocol list —— 协议信息
1. protocol list 是什么
-
存储类遵循的协议
-
包含:
-
必选方法
-
可选方法
-
主要用于:
- conformsToProtocol:
- Runtime 查询
八、class_rw_t / class_ro_t —— 可变与只读区
1. class_ro_t(只读)
-
编译期确定
-
存储:
- 原始方法列表
- ivar list
- property list
2. class_rw_t(可写)
-
运行时动态生成
-
存储:
-
Category 方法
-
动态添加的方法
-
这也是 Category 能“修改类行为”的根本原因。
九、Meta Class —— 类方法的归宿
1. Meta Class 是什么
- 类方法不是存在 Class 里
- 而是存在 Meta Class 的 method list 中
[Class foo]
→ 查找 Meta Class 的 cache / method list
十、一张完整 Runtime 结构图(逻辑)
instance
└─ isa → Class
├─ isa → Meta Class
├─ superclass
├─ cache
├─ method list
├─ property list
├─ ivar list
├─ protocol list
└─ class_rw_t / class_ro_t
十一、终极理解(非常重要)
-
方法调用性能 = cache 决定
-
行为修改能力 = method list + rw 区
-
内存布局 = ivar list 决定
-
反射能力 = property / protocol 提供
它们各司其职,互不混乱。
十二、一句话总结
Class 是 Runtime 的作战单元:
cache 决定快慢,method list 决定行为,
ivar 决定内存,property 决定语义,
isa 决定你是谁。
理解这一层结构,
你就真正理解了 Objective-C Runtime 的“骨架”。