上一篇我们着重讲了dyld和objc的关联 今天继续深入了解后续的流程
上篇我们也了解到了_read_images的流程 首先继续深入了解map_images中的_read_images。
_read_images
那我们要分析类的加载。就断点调试一波。找到关于类的方法
根据注释我们注意这块是探索类,于是我断点调试了一下 cls 是地址 而newcls就变成了名字
那么readClass里面我们去看个究竟~~~
readClass分析
我们从上面得出的结论是。readClass 把 cls和类名关联起来的~。那么我们继续分析
miss和fixup什么的都不是重点 分析重点感觉addNamedClass和addClassTableEntry很有用 进行一波调试准备
先筛选出我自己创建的类名
下面进行调试
果然就是addNamedClass,给了cls名字
跟进发现是NXMapInsert进行了一些操作~~有兴趣的童鞋可以深入研究下~~
addClassTableEntry
显而易见就是将类添加到表中~~
类的加载过程(ro,rw,rwe的赋值)在什么时候进行的?我们继续探索~~
懒加载与非懒加载
懒加载:推迟到 第一次消息发送的时候~
非懒加载:当map_images的时候,加载所有类数据的时候就加载
懒加载和非懒加载的区别标志:当前类是否实现load方法(大家都知道load在main函数之前,其实就是你进入main之前我就加载你了)
非懒加载分析
我们调试的时候没有走到这里,说明我们没有的类实现load,
那我们加上load方法试试
果然进来了 实现load方法就属于非懒加载~~
我们通过断点调试,发现他走的是 realizeClassWithoutSwift(cls, nil);。那么我们研究下这个方法
realizeClassWithoutSwift
我们的类先实现一些方法 并且筛选下我们的类便于调试
代码比较多我就讲重点~~ cls如果实现就返回 之后就是设置rw ro
递归 父类元类 走本方法
继承连与isa走向关联了
最后这个分类相关方法
懒加载分析
我们把load方法去掉 看下bt和堆栈
最终也会走 realizeClassWithoutSwift,不过他是通过方法查找的时候实现类。
* 1: 懒加载类情况 数据加载推迟到第⼀次消息的时候
lookUpImpOrForward
realizeClassMaybeSwiftMaybeRelock
realizeClassWithoutSwift
methodizeClass
调用堆栈: [LGPerson alloc] --> objc_alloc -->callAlloc --> _objc_msgSend_uncached -->lookUpImpOrForward -->initializeAndLeaveLocked-->initializeAndMaybeRelock-->realizeClassMaybeSwiftAndUnlock-->realizeClassMaybeSwiftMaybeRelock --> realizeClassWithoutSwift
* 2: ⾮懒加载类情况 map_images的时候 加载所有类数据
_getObjc2NonlazyClassList
readClass
realizeClassWithoutSwift
methodizeClass
调用堆栈:_dyld_start --> _objc_init --> _dyld_objc_notify_register --> dyld::registerObjcNotifiers --> dyld::notityBatchPartial --> map_images -->map_images_nolock --> _read_images --> realizeClassWithoutSwift
分类
首先通过clang -rewrite-objc main.m -o main.cpp 看下结构
分类的本质,就是一个 _category_t类型的结构体
分类的加载
在上面,我们已经通过 methodizeClass中找到了,分类的加载 attachToClass
断点调试发现并没有走下面的if~~
加上load方法就进去了
看下重点代码
如果存在,就直接获取,如果不存在,就开辟创建
rwe是在分类的添加的时候才进行处理,所以在这个时候才会进行初始化。
在经过一翻查询后,可以得到分类的添加处理在addMethod、addPro、addprotocol的时候都会进行处理。未完待续~~~
网友评论