类的加载底层原理探究之分类加载

451 阅读3分钟

前言

在优秀的开发者眼里类充当着无比重要的一个角色,那么类的底层加载流程是什么样子的呢?下面我们一起来探究

  • 储存过程中有三个重要类型:ro rw rwe roreadOnly,只读类型的memory,处于沙河路径,术语为clean memory

rw: readAndWrit,读写memory,运行时内存(脏内存),app运行时的读写内存,术语dirty memory

rwe: readAndWritExtention,对rw的拓展(听起来似乎与类别有某种关系)

一、attachCategories探究

1、rwe赋值流程

那么探索从内存出发,根据名字初步推断类别很有可能储存在rwe中,objc底层源码中探索发现rwe赋值auto rwe = cls->data()->extAllocIfNeeded()调用了extAllocIfNeeded函数

225AA5F552EBDA94CB866B12D9A546FB.jpg cmd+左键点进去发现似乎是赋值流程 3FBA39EE8C25CBC7B08D4CF32BB59632.jpg 那么接下来我们只需要全局搜索哪些地方调用了extAllocIfNeeded的赋值函数,就可以找到哪些情况对rwe做了赋值处理

2、调用了赋值函数的函数有哪些?

经过一些列的搜索发现以下函数

attachCategories //调用了1次 附加类别

objc_class::demangledName //调用了2次  demangled 名字

class_setVersion //调用了1次  类集版本

addMethods_finish //调用了1次  添加方法完成

BOOL class_addProtocol //调用了2次 类添加协议

objc_duplicateClass //调用了1次  objc复制类

我们这次的探究目的是研究分类,这些函数中与分类有关的貌似只有attachCategories

3.attachCategories探索

继续上探,看哪些方法调用了attachCategories 全局搜索发现只有两个函数调用了attachCategories方法 B69CA10DAE0B31DDC8D7E943C5D8D58B.jpg

attachToClass //附加到类

load_categories_nolock //加载分类->解锁

既然只有两个我们就一个一个来探索,非常的nice

3.1、attachToClass(翻译意思似乎是给类添加什么东西,感觉跟分类似乎关系非常的密切)

探索哪些方法调用了attachToClass函数,全局搜索发现只被调用了三次而且都在一个函数methodizeClass里,很完美

methodizeClass //整理类

很完美

4、methodizeClass探索

44F2D380E65627623FE87070712191AF.jpg

通过3.1我们发现三次调用attachToClass函数,其中两次是在if语句里previously存在时调用的

那么previously是什么东西?又是从哪里来的呢?出于好奇我们一探究竟

327806F62CCF28A4FF2B145EDA024A42.jpg 找到出处发现previously是在methodizeClass函数中的class类型的一个参数

4.1、那么哪些函数调用了methodizeClass函数呢?继续进行全局搜索,只有realizeClassWithoutSwift(类加载函数)调用了methodizeClass函数,而且也只是一个参数

02DA1E1858553A38608E2FABBAF33E27.jpg 继续向上层查找 ED31F81A6785B145DEDCD11C0ABFA0DA.jpg 48239492C2CDC836E7EE0CA0F4277575.jpg 全是nil...看样子可能苹果底层开发者预留的备用类

OK好奇心已经满足,我们回到正途继续探索

5.类别的最终出处realizeClassWithoutSwift(类加载函数)

由4.1探索过程中我们已经发现了调用methodizeClass函数的上一层方法是realizeClassWithoutSwift ---- 类加载函数

总结、最终有回归到了类的加载中来,我们不知不觉中已经理清楚了分类加载的一条线

流程如下

graph TD
realizeClassWithoutSwift --> methodizeClass --> attachToClass --> attachCategories --> extAllocIfNeeded

第二条线路 --> load_categories_nolock --> attachCategories --> extAllocIfNeeded

二、attachCategories流程之load_categories_nolock流程

写字好累,经过层层探索终于得到第二条线的流程很完美

得出完整的流程图

graph TD
realizeClassWithoutSwift --> methodizeClass --> attachToClass --> attachCategories --> extAllocIfNeeded

_objc_init_image --> _read_images --> load_categories_nolock --> attachCategories --> extAllocIfNeeded

map_images --> map_images_nolock --> _read_images --> load_categories_nolock --> attachCategories --> extAllocIfNeeded

_objc_init --> load_images --> loadAllCategories --> load_categories_nolock --> attachCategories --> extAllocIfNeeded