Day5-Objective-C Runtime 基础结构
Objective-C Runtime 基础结构
Objective-C 运行时系统(Runtime)是 Objective-C 语言的核心部分,它在程序运行期间负责管理类、对象、方法调用等行为。
主要的结构体和组件包括:
1. objc_class
(类结构体)
1 | struct objc_class { |
注意:现代 Runtime 中,结构体已经变化了,上述是经典(早期)的描述,新的版本更复杂且高度封装。
2. objc_object
(对象结构体)
1 | struct objc_object { |
- 每一个对象底层其实就是一个指针,最重要的成员就是
isa
。 isa
既可以指向 Class,也可以指向 Meta-Class(元类)。
3. objc_method
(方法结构体)
1 | struct objc_method { |
SEL
是方法名的唯一标识。IMP
是函数指针,本质上就是 C 函数的地址。
4. objc_ivar
(成员变量结构体)
1 | struct objc_ivar { |
- 成员变量的信息,包括名字、类型和内存位置。
5. objc_property
(属性结构体)
在现代 Runtime 里面,属性也有自己的结构:
1 | typedef struct { |
- 属性其实是成员变量 + 一些特定特性(getter/setter规则)。
小总结
组件 | 作用 |
---|---|
objc_object |
所有对象的基础 |
objc_class |
类对象描述结构 |
objc_method |
方法的定义 |
objc_ivar |
成员变量定义 |
objc_property |
属性定义 |
进阶补充
在 现代 Objective-C Runtime(如 iOS 14+),这些结构体实际上被进一步封装优化,比如:
- 类使用
objc_class
和objc_data_bits_t
(联合体)分离了缓存、只读数据等。 - methodList 也使用更紧凑的链表存储。
- isa 指针通过 isa 指针优化(ISA指针打包) 包含了更多信息,比如引用计数、是否有C++析构函数等。
现代 Objective-C Runtime 的优化
- objc_class 和 objc_data_bits_t 的分离
早期(传统)的结构:
在早期的 Objective-C Runtime 中,类对象(objc_class)包含了所有关于类的描述信息,包括:
- isa 指针(指向元类)
- super_class(父类指针)
- 成员变量、方法列表、属性等
这种结构虽然简单,但随着 iOS 设备性能的提高,运行时系统也需要对这些数据结构进行优化。
现代优化:
在 iOS 14 及之后的版本中,Objective-C Runtime 通过 分离 类的各个组成部分,提高了性能和内存效率。
objc_class 现在主要包含 元类的引用,而其它数据(如方法列表、属性、成员变量等)被移到了 objc_data_bits_t 结构中。这种方式的好处是:
- 缓存友好:类的元数据可以被存储在内存的紧凑区域,提高了缓存命中率。
- 分离存储:类数据和方法数据分开存储,避免了冗余的内存占用。
- 增强的灵活性:可以在不同的硬件架构下对这些数据进行不同的布局,以便更好地适配不同的内存和处理器特性。
例子:
objc_class 结构变得非常简洁:
1 | struct objc_class { |
而 objc_data_bits_t 则包含了实际的数据部分:
1 | union objc_data_bits_t { |
- methodList 存储的优化
早期存储:
传统的 methodList 是基于链表(Linked List)存储的。这种方式虽然简单,但查找方法时效率较低,尤其是在类层级很深或者方法很多的情况下。
现代优化:
在现代的 Runtime 系统中,methodList 不再是单纯的链表。它现在采用了一种 紧凑的链表结构,并且结合了 哈希表(Hash Table) 或者 二叉搜索树(Binary Search Tree),大大提高了方法查找的效率。
- 哈希表:通过哈希值来存储方法,查找操作时间复杂度为 O(1)。
- 二叉搜索树:如果方法列表较大,可能使用树结构来提高查找性能(特别是方法名排序后)。
这种优化使得对于频繁调用的方法,能够以更高的效率进行查找。
优化的好处:
- 方法查找速度更快。
- 降低了内存占用,尤其在方法很多的类中表现尤为突出。
- isa 指针优化(ISA指针打包)
早期 isa 指针:
早期的 isa 指针实际上是一个单纯的指针,它指向当前对象所属的类。当我们需要判断一个对象的类型时,必须通过这个指针进行查找。这个过程虽然有效,但随着内存和处理器架构的变化,其效率并没有得到最优的利用。
现代优化:
iOS 14 及之后的版本引入了 ISA 指针打包(ISA pointer packing) 的概念,使得 isa 指针变得更加高效。具体来说:
- 压缩指针:isa 不仅仅是一个指针,它包含了更多的信息,包括:
- 引用计数:可以通过 isa 字段直接获取对象的引用计数(而不需要额外的字段)。
- C++ 析构函数支持:对于 C++ 对象,isa 可以包含一个标记,表明该对象是否有 C++ 析构函数需要调用。
- 指针压缩:针对 64 位设备,指针已经被压缩,节省了内存空间。
- 指针布局:通过优化指针的布局,可以减少内存访问的延迟。例如,将常用的标记和信息放在 isa 中,减少了缓存缺失的概率。
结构变化:
1 | struct objc_object { |
这种优化使得:
• 内存使用:减少了内存占用。
• 效率提升:访问对象所属类时的效率大幅提高。
总结
在现代 Objective-C Runtime 中,结构体的优化和指针的打包大大提升了系统的性能,尤其是在内存占用和方法查找速度上。重点优化如下:
• objc_class 和 objc_data_bits_t 的分离:提高了内存布局的紧凑性和效率。
• methodList 的优化:结合哈希表和二叉搜索树,提高了方法查找的效率。
• isa 指针优化:通过指针打包,减少了内存占用,并加速了对象的类型查找和引用计数管理。
这些改进的核心目的是:提升性能、减少内存占用,特别是在 iOS 设备上,确保运行时系统能够在有限的硬件资源上高效运行。