OC底层原理14-类的加载原理上

272 阅读2分钟

前言

  • dyld->images->内存->LGPerson(方法-协议)
  • images(macho)->地址->表->类->初始化(rw-ro

一.objc_init分析

1.environ_init 环境变量打印

Xnip2021-07-25_16-39-09.jpg

打印结果

Xnip2021-07-25_16-40-29.jpg

1.OBJC_DISABLE_NONPOINTER_ISA 不使用NONPOINTER_ISA 举例

打印p的内存 p/t末尾显示1证明是NONPOINTER_ISA

Xnip2021-07-25_16-42-37.jpg

这里设置一下 Xnip2021-07-25_16-45-17.jpg 运行一下 打印p的内存 p/t末尾显示0证明是POINTER_ISA

Xnip2021-07-25_16-46-27.jpg

2.OBJC_PRINT_LOAD_METHODS 打印所有类使用load的方法

Xnip2021-07-25_16-50-44.jpg

运行一下 Xnip2021-07-25_16-53-32.jpg

3.终端打印环境变量 终端输入export OBJC_HELP=1 输入ls打印如下

Xnip2021-07-25_16-58-26.jpg

2.tls_init 关于线程key的绑定-比如每线程数据的析构函数(后面分析)

3.static_init 运行C++静态构造函数 在dyld调⽤我们的静态构造函数之前,libc 会调⽤ _objc_init(),因此我们必须⾃⼰做

自动调用C++构造函数 先调用系统的

Xnip2021-07-25_17-18-00.jpg 在调用load的方法 Xnip2021-07-25_17-19-12.jpg 在调用main函数里面的构造函数

Xnip2021-07-25_17-18-40.jpg

4.runtime_init runtime运⾏时环境初始化,⾥⾯主要是:unattachedCategories,allocatedClasses 后⾯会分析

5.exception_init 初始化libobjc的异常处理系统

Xnip2021-07-25_19-23-39.jpg 调用这个方法_objc_terminate Xnip2021-07-25_19-24-22.jpg uncaught_handler这个方法 底层在哪里注册的 Xnip2021-07-25_19-25-21.jpg

上层API调用的这个方法

Xnip2021-07-25_19-31-35.jpg

6.cache_t::init() 缓存条件初始化

7._imp_implementationWithBlock_init(); 启动回调机制。通常这不会做什么,因为所有的初始化都

8._dyld_objc_notify_register(&map_images, load_images, unmap_image);

  • &map_images:指针传递 管理⽂件中和动态库中所有的符号(class Protocol selector category)
  • load_images:值拷传递 加载执⾏load⽅法

二.read_images流程引入

1.map_images

Xnip2021-07-25_19-50-51.jpg 调用map_images_nolock

Xnip2021-07-25_20-13-54.jpg 调用_read_images 读取镜像文件

三.read_images主体流程

Xnip2021-07-25_20-38-40.jpg

Xnip2021-07-25_20-39-01.jpg

Xnip2021-07-25_20-39-16.jpg

四.readClass核心重点引入

read_images读取镜像文件读取到表里面通过地址还原怎么关联到类里面

Xnip2021-07-25_21-12-42.jpg 读取表里面的seldyld里面的sel进行对比 macho的地址不一定精准 需要修复 Xnip2021-07-25_21-13-17.jpg

Xnip2021-07-25_21-13-51.jpg

五.readClass分析

第一次进入 断点进入之后分析 是先把类添加到表中 Xnip2021-07-25_21-27-23.jpg

通过类的加载我们进入到realizeClassWithoutSwift这个方法

Xnip2021-07-25_21-37-55.jpg