前语

上一篇博客咱们了解到dyld->libsystem->libdispatch->_objc_init这样一个流程。那么下面咱们来了解一下objc_init里边究竟做了些啥。

objc_init剖析

  • environ_init环境变量初始化

在源码里边经过如下代码来检查环境变量:

    for (size_t i = 0; i < sizeof(Settings)/sizeof(Settings[0]); i++) {
const option_t *xcode怎样运转c++程序opt = &Settings[i];
_objc_in服务器ipforswift怎样读m("%s: %s", opt->源码年代坑人env, opt->help);
_objc_inform(xcode轿车"%s is set", opt->env);
}

源码是什么意思能够经过在终端里边输入export OBJC_HELP=1,然后再输源码年代坑人lldb:打印信息如下

dyld之类的加载
咱们能够在xcode里边设置一下OBJC_PRINT_IMAGES设置一下这个环境变量,就会打印出。经过Edit Scheme ->Run就能够设置。

  • tls_Swiftinit:关于线程key的绑定,比方每swiftkey个现场的析构函数
  • static_init:运⾏C ++静态结构函数。在dyld调⽤之前自己先调用
  • runtime_init:首要是初始化unattachedCategoriesallocatedClasses两个表。
  • e源码本钱xception_init:失常初始化,咱们常用的objc_setUncaughtExceptionHandler处理崩溃后失常,线程是什么意思或奔溃日志上传服务器。
  • cache_t::init()缓存条件初始化
  • _imp_implementationWithBlock_init:发起回调机制。一般这不会做什么,由于一切的初始化都是慵懒的,可是对于某些进程,咱们会刻不容缓地加载trampolixcode教程nes dylib.
  • _dyld_objc_notify_register,将map_images load_images unmap_image办法赋值给dyld去触发调用

map_images剖析

  • map_images_nolock

swift体系个办法首要是找到machoxcode怎样设置成中文服务器是什么image,然后调用_read_imswiftcode是什么意思中文ages

_read_images剖析Swift

这个里边,代码有许多,当时苹果工程师做了许多的日志打印。咱们能够经过这个xcode教程来分红小模块去剖析。

  • 源码交易平台排行件操控进行第一次加载

创立NXMapTable表,巨swiftcode是什么意思中文细为4/3 *totalClasses。这个表是一张class总表;与上面的allocatedClasses表是有差异的,后边的是存储现已alloc的。

  • 批改预编译阶段的 @selector 的swiftkey混乱问题.

为什么会需求批改呢?这是由于,咱们从image里边获取的办法的地址是没源码年代坑人有加上ASLR也便是基地址,需求经过dyxcode轿车ld加上基地址后从头批改。

  • 读取类readClass、处理没有被清理的类
  • 批改重映射一些没有被镜像文件加载进来的类rem源码怎样做成app软件apClassRef
  • 批改一线程撕裂者些音讯fixupMessageRef
  • 读取类的协议readProtocol
  • 批改没有被加载的协议remapProtocolRef
  • 加载分类load_categories_nolock
  • 加载类r源码年代坑人ealizeClassWithoutSwift
  • 结束新解析的未来类

下面咱们首要剖析一下readClass

readClass剖析

readClass服务器怎样建立办法中增加如下代码,这样就能够研讨咱们自定义的类是怎样读取的。

dyld之类的加载
断点持续实行:

dyld之类的加载
发现并没有实行ro,rw相关的赋值。
断点持续下一步,会调用addNamedClass

dyld之类的加载
这时会把class刺进到总表中

  • 持续实行会递归调用addCxcode轿车lassTableEntry
addClassTableEntry(Class cls, bool addMeta = true)xcode中文
{
runtimeLock.assertLocked()xcode怎样运转c++程序;
// This class is allowed to be a known class via the sharexcode是什么d cache or via
// data segments, but it is not allowed to be in the dynamic table already.
auto &set = objc::allocatedClasses.g服务器怎样建立et();
ASSERT(set.find(cls) == set.end());
if (!isKnownClass(cls))
s服务器租借多少钱一年et.insert(cls);
if (addMeta)
addClassT线程的概念ableEntry(cls->ISA(), false);
}

class刺进到allocatedClasses表中,假设有元类,把元类也刺进进去。

类的结束realizeClassWithoutSwift

  • 新建一个QHPswiftererson类,然后在里边增加load办法,在代码里边增加xcode是什么软件如下代码,这样就能够研讨咱们自定义的类

dyld之类的加载
持续实行进入到realizeClassWithoutSwift办法。

  • ro 赋值给rw

dyld之类的加载

  • 设置父类和元类联系

dyld之类的加载

  • 条理化class

dyld之类的加载

meth线程池创立的四种odizeClass剖析

下面咱们持续进入methodizeClass办法,增加如下代码,这儿多了一个元类的判别,由于元类和自身类的姓名相xcode教程同:

dyld之类的加载
打印rwe:发现为nil

dyld之类的加载

dyld之类的加载

  • 证明rwe->properties.attachLists(&proplist, 1);rwe->protocolsswiftcode是什么意思中文.attachLists(&protolist, 1);
  • 假设有办法就会调用prepareMethodLists,这个线程池办法实际上是经过地址对办法进行排序,下面的代码能够验证

dyld之类的加载

  • 将分类增加到主类attachToClass,这个办法swiftcode是什么意思中文下篇博客再分服务器是什么
  • 所以mexcode教程thodizeClass首要是办法排序和将分类增加到主类中。

懒加载和非懒加载

上面咱们在自定义的类中增加了load办法,现在咱们去掉线程池创立的四种.然后再运转。发现一个古怪的现象:

dyld之类的加载
这是为什么???下面咱们在main里边调用QHPerson的办法swift怎样读。持续运转,这个时分进入了,只不过不是走的之前的流程:

dyld之类的加载
经过堆栈,能够看出是在main函数之后走的音讯发送的流程。

总结

  • 假设自定义的类结束了load办法,(非懒加载),会经过dyld->objc_init->(实例化主程序)->read_image->read_class去加载类。
  • 假设没有结束load办法,(懒加载),会在第swift怎样读一次调用方针办法的时分去,走音讯转发流程去结束
  • 懒加载这样的处理方式会大大优化app的发起时刻