OC底层原理05:objc_alloc探索
前言
本章主要探索继承自 NSObject
的类 ZJPerson
和 NSObject
调用 alloc
的区别
准备工作
1、下载objc4-781 源码。
2、编译源码,可参考iOS-OC底层原理02:Objc4源码编译
NSObject调用alloc探索
1、第一步:在main函数中实现下面的代码,并下断点:
2、第二步:到源码下断点到 + (id)alloc
,先 取消断点
,等程序运行到目标行在去跟踪断点
,原因在前面查找源码已经讲过,在此不在说明:
我们发现并没有进来,我滴天呐,说明调用的不是 alloc
3、第三步:我们换一种方式去查看源码,打开Debug->Debug WorkFlow->Debug->Debug Workflow->Alway Show Disassembly
查看汇编:
我们发现底层源码调用的是 objc_alloc
,到底是不是呢?接下来我们 二次验证
一下
**4、第四步:二次验证->先取消Debug查看方式,到源码中下断点到 objc_alloc
**
我们发现 Class cls
这个类确实是 NSObject
,验证了我们上面的调用过程
5、第五步:继续往下走,callAlloc
内部调用流程
我们发现 callAlloc
内部最终调用的是 _objc_rootAllocWithZone
最终和iOS-OC底层原理03:alloc&init&new探索alloc调用流程不谋而合
6、结论:我们用流程图去表达一下调用流程
继承类ZPerson调用alloc真实调用流程
1、第一步:在 main
函数中实现 ZJPerson
类的 alloc
方法进入alloc方法,并下断点:
2、第二步:打开 Debug->Debug WorkFlow->Debug->Debug Workflow->Alway Show Disassembly
查看汇编:
3、第三步:通过在源码中下断点 objc_alloc
和 alloc
去跟踪具体先执行过程:
1 | 跳转至objc_alloc的源码实现 |
4、第四步:跳转至 callAlloc
的源码实现
1 | // Call [cls alloc] or [cls allocWithZone:nil], with appropriate |
5、第五步:跳转至 return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
的内部源码实现
1 | objc_msgSend(void /* id self, SEL op, ... */ ) |
系统通过特殊消息发送:sel - imp
做了一层处理,最终执行到 alloc
,根本就是系统通过LLVM特殊消息发送做的处理,有兴趣的小伙伴可以通过LLVM源码去探索一下
6、第六步:跳转至 alloc
源码实现
1 | + (id)alloc { |
7、第七步:跳转至 _objc_rootAlloc
源码实现,我们可以验证 cls
是ZJPerson
8、第八步:跳转至 _objc_rootAllocWithZone
源码实现
1 | // Call [cls alloc] or [cls allocWithZone:nil], with appropriate |
9、第九步:跳转至 _class_createInstanceFromZone
源码实现
1 | NEVER_INLINE |
10、第十步:内部调用 cls->instanceSize、calloc、obj->initInstanceIsa(cls, hasCxxDtor)、return obj
方法返回对象,具体流程不再赘述
11、总结:ZJPerson的alloc调用流程图:
ZJPerson的alloc和NSObject的alloc区别
ZJPerson
会走两次objc_alloc -> alloc
NSObject
只走一次objc_alloc
- Post title:OC底层原理05:objc_alloc探索
- Post author:张建
- Create time:2020-09-12 02:04:27
- Post link:https://redefine.ohevan.com/2020/09/12/OC底层原理/OC底层原理05:objc-alloc探索/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.