iOS 底层原理 17:类的加载(上)
2023-12-30 05:45:40
类的加载:在 Objective-C 运行时背后的机制
类的加载过程
当 Objective-C 代码中某个类被引用时,运行时将经历一个复杂的加载过程,以将该类及其元数据加载到内存中。这个过程涉及多个步骤:
1. 定位类
运行时首先在内存中搜索该类的元数据。如果类尚未加载,则会启动加载过程。
2. 加载类
运行时从可执行文件中读取类的元数据并将其加载到内存中。此元数据包括类的结构、方法列表和属性列表。
3. 初始化类
运行时调用类的 +load
方法来初始化该类。+load
方法负责执行类的静态初始化,例如分配内存和设置类变量。
4. 准备类
运行时为该类分配内存并将其构造函数添加到其方法列表中。
5. 解析类
运行时解析类的属性和方法,并将它们添加到类的完整方法列表中。
值得注意的是,这些步骤并非严格按照顺序执行,某些步骤可能会重叠或并行执行。
map_images 和 load
map_images 是 dyld 中一个关键函数,负责将可执行文件中的段映射到内存中。在类加载期间,map_images 执行以下操作:
- 在可执行文件中查找类的元数据
- 将类的元数据映射到内存中
- 重定位类的指针以指向内存中的正确位置
load 是一种类方法,负责执行类的静态初始化。当加载类时,+load
方法会自动调用。+load
方法可以执行以下操作:
- 分配内存以存储类的静态变量
- 设置类的静态变量,例如类名和版本号
- 将类注册到 Objective-C 运行时中
代码示例
@interface MyClass : NSObject
// 类变量
static int sharedVariable;
// 构造函数
+ (instancetype)alloc {
// 在 `+alloc` 方法中调用 `+load` 方法
[self load];
return [super alloc];
}
// `+load` 方法负责静态初始化
+ (void)load {
// 初始化 sharedVariable
sharedVariable = 42;
}
@end
在上面的示例中,+load
方法在类的 +alloc
方法中被调用,负责初始化类的静态变量 sharedVariable
。
结论
类的加载是一个至关重要的过程,它允许 Objective-C 代码与底层运行时进行交互。通过理解 map_images
和 load
函数在这一过程中的作用,我们可以更好地理解 Objective-C 运行时的内部工作原理。
常见问题解答
-
类的加载过程中的“重定位”是什么意思?
重定位涉及更新类的指针,以指向内存中正确的位置。这是由于可执行文件在加载时被移动到不同的内存地址,需要更新指针才能访问正确的内存位置。 -
+load
方法的目的是什么?
+load
方法用于执行类的静态初始化,例如分配内存、设置类变量和注册类到 Objective-C 运行时。 -
为什么
+load
方法在+alloc
方法中被调用?
+alloc
方法是类在创建新实例时调用的第一个方法,因此将其作为+load
方法的调用点可确保类在任何实例被创建之前初始化。 -
Objective-C 运行时如何使用类的元数据?
类的元数据包含有关类的重要信息,例如其结构、方法列表和属性列表。运行时使用此信息来解析类并支持消息传递和方法调度。 -
map_images 和 load 之间有什么区别?
map_images
负责将类从可执行文件中映射到内存中,而load
负责执行类的静态初始化。