返回

iOS 底层原理 17:类的加载(上)

IOS

类的加载:在 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_imagesload 函数在这一过程中的作用,我们可以更好地理解 Objective-C 运行时的内部工作原理。

常见问题解答

  1. 类的加载过程中的“重定位”是什么意思?
    重定位涉及更新类的指针,以指向内存中正确的位置。这是由于可执行文件在加载时被移动到不同的内存地址,需要更新指针才能访问正确的内存位置。

  2. +load 方法的目的是什么?
    +load 方法用于执行类的静态初始化,例如分配内存、设置类变量和注册类到 Objective-C 运行时。

  3. 为什么 +load 方法在 +alloc 方法中被调用?
    +alloc 方法是类在创建新实例时调用的第一个方法,因此将其作为 +load 方法的调用点可确保类在任何实例被创建之前初始化。

  4. Objective-C 运行时如何使用类的元数据?
    类的元数据包含有关类的重要信息,例如其结构、方法列表和属性列表。运行时使用此信息来解析类并支持消息传递和方法调度。

  5. map_images 和 load 之间有什么区别?
    map_images 负责将类从可执行文件中映射到内存中,而 load 负责执行类的静态初始化。