揭秘iOS底层:剖析类加载(上)
2023-09-09 18:12:09
揭秘 iOS 类加载的幕后黑手
引言
探索 iOS 底层的奥秘之旅仍在继续,这一次,我们将深入研究类的加载机制。深入了解类的加载过程,对于 iOS 开发人员来说至关重要,因为它赋予了我们深入了解应用程序行为和提高性能的能力。
Mach-O:类的庇护所
Mach-O 是一种二进制文件格式,用于存储 iOS 应用程序的可执行代码、数据和元数据。类的元数据,例如类名、父类和方法列表,都整齐地存储在 Mach-O 的 __DATA
段中,具体位于 __objc_classlist
和 __objc_catlist
部分。
objc_class:类的蓝图
objc_class
结构体是类的核心数据结构,它包含了类的元数据,如类名、父类、实例变量和方法列表。当类被加载时,Objective-C 运行时会创建相应的 objc_class
实例。
struct objc_class {
Class isa;
Class superclass;
const char *name;
long version;
long info;
long instance_size;
long ivars;
const char **ivar_list;
const char **method_list;
const char **protocol_list;
const char **ivars;
const objc_method_description **methods;
const objc_property_t **properties;
const objc_class **protocols;
};
元数据的加载:从 Mach-O 到运行时
当类被加载时,Objective-C 运行时会从 Mach-O 文件中提取元数据,并填充 objc_class
结构体。这个过程主要涉及以下步骤:
-
加载 Mach-O 文件: 系统使用
dlopen
加载 Mach-O 文件,并将 Mach-O 的基地址存储在全局变量_mh_execute_header
中。 -
定位
objc_classlist
: 使用 Mach-O 文件中的load_commands
表,找到LC_SEGMENT
命令,然后在段信息中定位__DATA
段。接着,在__DATA
段中找到__objc_classlist
部分的地址。 -
遍历
objc_classlist
: 遍历__objc_classlist
部分,读取每个objc_class
结构体的信息,并填充到 Objective-C 运行时的哈希表中。
关联对象的加载:附加的视角
除了元数据,类还可以与关联对象相关联。关联对象是与类或对象关联的附加数据,通常用于存储额外的信息或实现特定功能。Objective-C 运行时通过关联列表(objc_objectlist
)管理关联对象。
代码段的加载:方法的舞步
类的代码段(方法实现)存储在 Mach-O 的 __TEXT
段中,具体位于 __text
和 __cstring
部分。当类被调用时,Objective-C 运行时会将代码段加载到内存中,并将其解析为机器指令。
总结:iOS 类加载的蓝图
通过探索 Mach-O 文件结构和 objc_class
结构体,我们揭开了 iOS 类加载的神秘面纱。Objective-C 运行时从 Mach-O 文件中提取元数据,填充 objc_class
结构体,并管理关联对象,从而完成类的加载过程。
深入理解底层机制,对于 iOS 开发人员来说至关重要,它赋予了我们洞察应用程序行为和提高性能的能力。在下篇博客中,我们将继续深入探讨类加载,重点关注方法解析和代码段加载的细节。敬请期待!
常见问题解答
-
objc_class
结构体包含了哪些信息?objc_class
结构体包含了类的元数据,如类名、父类、实例变量和方法列表。
-
Objective-C 运行时如何加载元数据?
- Objective-C 运行时从 Mach-O 文件中提取元数据,并填充
objc_class
结构体。
- Objective-C 运行时从 Mach-O 文件中提取元数据,并填充
-
关联对象是什么?
- 关联对象是与类或对象关联的附加数据,通常用于存储额外的信息或实现特定功能。
-
代码段存储在哪里?
- 类的代码段存储在 Mach-O 的
__TEXT
段中。
- 类的代码段存储在 Mach-O 的
-
Objective-C 运行时如何加载代码段?
- 当类被调用时,Objective-C 运行时会将代码段加载到内存中,并将其解析为机器指令。