上一篇我们讲述了 dyld 的加载流程 这篇文章我们来搞清楚dyld和objc的关联。
首先看一下objc4-781官方源码_objc_init方法
environ_init(); //环境变量的读取初始化
tls_init(); //自动释放池、runloop线程相关
static_init(); //运行C ++静态构造函数
runtime_init(); //新增的。runtime运行时环境初始化
exception_init(); //异常捕获初始化
cache_init(); //缓存条件初始化
_imp_implementationWithBlock_init(); //启动回调机制
下面着重分析下_dyld_objc_notify_register
_dyld_objc_notify_register 这个方法是跨库执行的,在苹果开源的 dyld 源码里面可以找到,然后看到调用了 dyld::registerObjCNotifiers 这个方法:
load_images
接下来我们分析一下registerObjCNotifiers方法的第二个参数init,(也就是_dyld_objc_notify_register方法中的load_images参数)方法里面有sNotifyObjCInit = init;这个赋值语句,接下来我们在dyld源码中全局搜索一下sNotifyObjCInit,会发现在notifySingle方法中有sNotifyObjCInit的调用:
所以在 ObjC 中 _objc_init 方法里调用的 _dyld_objc_notify_register 方法终于在 dyld 源码中找到其真正调用的地方,终于找到了它们真正的关联关系了。
map_images
那么_dyld_objc_notify_register方法中的map_images参数呢?接下来我们继续找registerObjCNotifiers方法中的sNotifyObjCMapped = mapped;这一赋值语句,在dyld源码中全局搜索一下sNotifyObjCMapped,同样会发现在notifyBatchPartial方法中有sNotifyObjCMapped的调用:
所以说 ObjC 中 _objc_init 方法的调用时离不开 dyld 的,它们之间有着紧密的联系。
我们还可以继续探索一下 map_images, 进入到 objc_781 源码,全局搜索相关的函数调用 map_images ,我们能进入相关的函数调用过程:
再进入到 map_images_nolock 方法中,我们能发现其中有很多加载相关类的信息 _read_images:
我们知道,map_images这个函数的主要功能就是为了映射相关的类信息,所以此处才是我们研究的重点,接着进入到相关的类方法的定义_read_images方法,顺着源码分析我们能得到很多关于类的信息:
• 1: 条件控制进⾏⼀次的加载
• 2: 修复预编译阶段的 `@selector` 的混乱问题
• 3: 错误混乱的类处理
• 4:修复重映射⼀些没有被镜像⽂件加载进来的 类
• 5: 修复⼀些消息!
• 6: 当我们类⾥⾯有协议的时候 : readProtocol
• 7: 修复没有被加载的协议
• 8: 分类处理
• 9: 类的加载处理
• 10 : 没有被处理的类 优化那些被侵犯的类
下篇文章继续讲解~~~
网友评论