提出问题

说到运用初始化之前,先提出三个问题,先想想这三个问题你的确明白了吗?

  1. load办法何时调用
  2. 子类、父类、分类的load办法的调用次序
  3. 子类、父类、分类的initialize办法的调用次序

在答复这三个问题之前首要要清晰的是整个app的加载进程是怎样的

编译进程

  • 源文件:载入.h、.m、.cpp等文件
  • 预处理:替换宏,删去注释,翻开头文件,产生.i文件
  • 编译:将.i文件转换为汇编语言,产生.s文件
  • 汇编:将汇编文件转换为机器码文件,产生.o文件
  • 链接:对.缓存视频兼并软件o文件中引证其他库的当地进行引证,生成终究的可实行文件

编译进程大致可分为以上五步,一起在这application儿还需要了解静态库动态库google

静态库

静态库的特征便是在链接阶段,就会把方针程序和引证的库一起打包到可实行文件中,静态库此刻就不能够更改了,这样做的利益是在编译完成后,假如方针程序不需要外部依托则能够直接实行,缺点正是对应其利益来讲,因为是静态库是直接复制的,所实例化需求以会构成方针程序体积增大,对功用是有损耗的。

动态库

与静态库相对比,动态库在编译的时期不会直接链接到方针程序中,方针程appointment序只会存储指向动态库的引证,在程序运行时才被载入,这样它的利益就有三个:

  • 减小了方针程序的体积因为并不会像静态库相同打包进去
  • 可运用同一片同享内存同一个库能够被多个运用程序来运用
  • 活络类似于热更新因为运行时才载入的特性使得动态库能够随时更实例化一个类

缺点便是比较于静态库因为所谓的活络,动态会丢掉一部分功用。

加载进程

从objc_init说起(一)
整个加载进程用这张图展示的十分明晰,这appleid儿一起要留神一个十分重实例化方针的关键字要的函数_d狗狗币yld_objc_notify_register
这个函数便是把整个程序打开runtime回调的初缓存文件在哪里步,系统库经过dyld管理,一起提供了运行时的特性。

void _objc_init(void)
{
stat宫颈癌疫苗ic bool initialized = false;
if (initialized) return;
initia实例化方针lizAPPed = true;
// fixme defer initialization until an objc-using image is found?
environ_init();
tls_init();
static_init();
lock_init();
exception_init();
_dyld_objc_notify_register(&map_images, load_images, unmap_image);
}

从objc_init说起(一)
那么经过以上的剖析,发现这儿是很有必要application去从dyld开始剖析,看看是怎样从dyld切换到runtime这儿的。

app发动的开始

从objc_init说起(一)
接下来会从dyld的源码中开始剖析

  • dyld整个工程中查找__dyl龚俊d_start能够看到这段是卸载汇编里的,APP一起这儿会调起一个函数dyldbootstrap::start

从objc_init说起(一)

  • 继续在工程里查找dyldbootstrap::start,整个函数源码共享网最重要的当地便是调起了dyldmain函数

从objc_init说起(一)

因为dy实例化英文ld::main这儿的代码十分长,此处仅展示部分重要代码,整个进程可实例化servlet类异常以划分为9步,接下来会分步来剖析整个进程

1.装备环境变量

这一步首要实例化方针的关键字是查看设置的环境变量
从objc_init说起(一)

2.查看同享缓存

查看是否打开了同享缓存,并且是否映射到了同享区域,例如系统的UIKit
从objc_init说起(一)

3.主程序的初始化

调用instantiateFromLoadedImage函数缓存和下载的区别加载可实行文件并生成ImageLoader方针
从objc_init说起(一)
进入instantiateFromLoadedImage函数

从objc_init说起(一)

其内部调用instantiateMainExecutable,为首要可实行文件创立映像,回来主程序
从objc_init说起(一)

4.刺apple实例化方针的关键字动态库

经过遍历DYLD_INSERT_LIBRARIES环境变量来加载悉数指定的动态库
从objc_init说起(一)

5.链接主程序

从objc_init说起(一)

6.链接动态库

从objc_init说起(一)

7.弱符号绑定

从objc_init说起(一)

8.实行初始化办法源码

从objc_init说起(一)

initializeMainExecutable为悉数刺进的dylibs都实行初始化,也便是runInitializers办法
从objc_init说起(一)

ru实例化是什么意思nInitializers办法中中心代码源码编辑器编程猫下载processInitializer缓存视频怎样转入相册s
从objc_init说起(一)

processInitializers在镜像列表中调用递归实例化,以树立未初始化的向上依托联络的新列表
从objc_init说起(一)recurs缓存视频怎样转入相册iveInitializatiGoon中有两块当地要留神notifySingledoInitialization
从objc_init说起(一)

notifySingle这儿源码的关键在于(*sNotifyObjCInit)(image->getRealPath(), image->machHeader())

从objc_init说起(一)
找到sNotifyObjCInit的赋值
从objc_init说起(一)
顺藤摸瓜找到调用的当地_dyld_objc_notify_register是不是十分眼熟这个函数,没错,这个便是我们一开始在libobjc中找到的函数

从objc_init说起(一)

从objc_init说起(一)
这时怎能看出notifySing缓存视频le是一个回调函数,会调起在libobjc中传入的load_appleidimages办法
那么load_images办法终究做了什么

load_images

从objc_init说起(一)

prepare_load_methods
从objc_init说起(一)schedule_class_load
在类中会递归加载load办法到loadable_classes这个表中,此刻留神实例化是什么意思加载次序,因为是appear递归加载,那么次序一定是找到先人类、父类、子类,以这种次序加载到表工商银行
从objc_init说起(一)add_category_to_loadable_list相同加载分类也是会将悉数分类的load办法加载到loadablgooglee_categories这张表中,因为分类不存在继承源码资本联络,故不像类的加载要采用递归加载的办法。
从objc_init说起(一)call_load_methods中先调用悉数类里面的load办法后接着调用分类里load办法

从objc_init说起(一)cal源码之家l_class_loads
从objc_init说起(一)
看到这儿就能够得到load_ima缓存视频兼并软件ge调用了悉数的l实例化类oad函数,这儿就能够答复了之前的答复,load办法的调用是先类,后分类,其中类的调用次序与之前加载次序是共同的,即先人类、父类、子类的次序。

doInitialization

刚才是把从dyld_start开始一路找到了libobjc中,那么objc缓存视频_init终究是怎样调用的,也便是dyld怎样到libojbc的呢?先回到recursivAPPeInitial实例化方针的关键字ization
从objc_init说起(一)
app安装下载儿相同有两个apple重要的函数doImageIn实例化方针itdoModInitFunctions

doImageInit

从objc_init说起(一)d工商银行o缓存视频兼并ImageInit这儿是循环加载办法的调用
从objc_init说起(一)doModInitFunctions循环加载了悉数Cxx文件
从objc_init说起(一)
走到这儿依旧是没发现objc_init是怎样调起源码下载的,这时去看下调用栈的实例化需求信息

从objc_init说起(一)
能够看到doImageInit后调用了libSys源码编辑器tem_initializer,那么去libSystem寻觅

从objc_init说起(一)

从objc_init说起(一)

从objc_init说起(一)

9.找到主程序进口即main函数

从objc_init说起(一)

initialize

文章刚开始说到的问题中,针对load的问题已剖析完成,接下来来看看appearinitialize,首要来看下是怎样调用的

从objc_init说起(一)
很显着已经是在main之后才开始调用的,显着晚于load的调用
首要找到lookUpImpOrForward

从objc_init说起(一)

从objc_init说起(一)

从objc_init说起(一)
此处又能够看到是递归调用,当悉数准备做好后,开始调用
callInitialize
从objc_init说起(一)

从objc_init说起(一)