12.2 谈谈Runtime的加载过程

2020-05-15  本文已影响0人  哈库呐玛塔塔__

https://www.jianshu.com/p/4fb2d7014e9e

iOS类的加载

runtime加载过程简述

runtime在加载的时候 ,通过dyld的一些操作,最终调用了runtime中的_objc_init函数,在这个函数中进行了一些初始化的操作,主要包括环境变量、线程方面、c++静态构造函数、异常处理。

紧接着注册了三个函数指针。map_Images  load_images 和 unmap_Images.

map_images其实是一个函数中转。_read_images 是map_images内的一个核心函数

先整体梳理一遍_read_images函数内部的逻辑:

加载所有类到类的gdb_objc_realized_classes表中。

对所有类做重映射。

将所有SEL都注册到namedSelectors表中。

修复函数指针遗留。

将所有Protocol都添加到protocol_map表中。

对所有Protocol做重映射。

初始化所有非懒加载的类,进行rw、ro等操作。

遍历已标记的懒加载的类,并做初始化操作。

加载所有Category,然后根据方法类型处理Class和Meta Class。

初始化所有未初始化的类。

_read_images方法的详细分析

_load_images方法的详细分析

参考+(void)load方法详解

简单小结:

1. 类在内存中的位置是在编译期间决定的,在之后修改代码,也不会改变内存中的位置。

2. 类的方法、属性以及协议在编译期间存放到了“错误”的位置,直到 realizeClass 执行之后,才放到了 class_rw_t 指向的只读区域 class_ro_t,这样我们即可以在运行时为 class_rw_t 添加方法,也不会影响类的只读结构。

3. 在 class_ro_t 中的属性在运行期间就不能改变了,再添加方法时,会修改 class_rw_t 中的 methods 列表,而不是 class_ro_t 中的 baseMethods,对于方法的添加会在之后的文章中分析。

上一篇下一篇

猜你喜欢

热点阅读