类的加载(上)

169 阅读2分钟

类的加载分为懒加载类和非懒加载类

  1. 非懒加载类::实现了 +(void)laod 方法
  2. 懒加载类 ::没实现了 +(void)laod 方法

app启动后,调用libsystem -->libdispatch --->libojc 由runtime的初始化进入 _objc_init

image.png

environ_init()环境变量的初始化

  1. 比如配置是否开启ISA指针优化
  2. 是否打印所有的动态库
  3. 是否开启taggedPoint优化(NSNumber,nsstring等) 等等 image.png

tls_init()创建线程的一些析构函数

tls操作系统为线程提供的单独的数据存储空间,存储当前线程的数据

image.png

static_init() 运行C++的静态的析构函数

  • Run C++ static constructor functions.
  • libc calls _objc_init() before dyld would call our static constructors,  Libc在dyld调用静态构造函数之前调用_objc_init()

runtime_init()初始化两张表

image.png

  • exception_init();异常处理的初始化
  • cache_t::init();缓存 SEL 和IMP初始化

初始化的任务完成,接下来开始加载类

image.png

load_image加载流程 load方法是线程安全的,底层有实现加锁

  1. 查找load方法,找到所有实现load方法的懒加载的类
  2. prepare_load_methods
  3. 调用load方法,通过do{} while();循环调用 父类 > 子类 > 分类里面的load方法
  4. call_load_methods()执行load

map_image函数调用流程

  1. preopt_init(): 关于共享缓存初始化和优化处理
  2. 读取可执行文件和动态库里面所有类,通过while循环,从文件的header里面读取所有的类
  3. sel_init()初始化内部使用的选择器表和注册选择器。 注册C++的构造函数和析构方法
  4. arr_init()初始化表

image.png

  1. _read_images
  • 1、默认支持开启指针优化 DisableNonpointerIsa = true;
  • 2、开启taggerPoint的优化(NSNumber,nsdata,nsstring等) disableTaggedPointers();
  • 3、创建一个表存放不在共享缓存中的数据,也不是非懒加载的类,只能通过getClass获取到的类

image.png 翻译:

  • //这是一个错误的名称:gdb_objc_realized_classes实际上是一个列表
  • //不包含在dyld共享缓存中的命名类,无论是否实现。
  • //这个列表排除了延迟命名的类,这些类必须要查找
  • //使用getClass钩子。
  1. // Fix up @selector references 修复selector方法调用,简单来说就是重定位方法
  • 从虚拟内存地址--->指向正确的内存地址
  1. fixupMessageRef 这个方法在系统底层做了方法转换,比如在调alloc方法的时候,通过fixupMessageRef函数 实现调用objc_alloc方法
  • alloc --->fixupMessageRef() ---> objc_alloc

image.png 6. 调用readClass,

  • 将已分配内存空间的 类 和 元类 放进allocatedClasses表里,
  • 调用函数 addClassTableEntry() 把类添加到allocatedClasses 表里
  1. 加载非懒加载类
  • //实现非懒加载的类(用于+加载方法和静态实例)
  • // Realize non-lazy classes (for +load methods and static instances)
  • 调用realizeClassWithoutSwift方法,将ro里面的数据存入rw中,实现非懒加载类的加载

image.png