当前位置: 首页 > news >正文

【iOS】alloc的实际流程

目录

前言

为什么不按源码流程调用?

alloc的调用流程


前言

在之前的博客中我们有学习到过alloc的底层原理,沿着源码一步步找到了alloc的调用链——alloc—>_objc_rootAlloc—>callAlloc—>_objc_rootAllocWithZone—>_class_createInstanceFromZone,但其实在实际的alloc过程中,并不是这个调用流程,如果对NSObject的alloc加上断点调试就会发现,alloc流程并没有进入源码,接下来我们来探究一下为什么会这样以及真实的调用流程。

为什么不按源码流程调用?

在实际运行中,[NSObject alloc][MyClass alloc] 这类调用通常不会真正进入 libobjc 的源码层(比如 _objc_rootAlloc,而是走了更加高效的底层路径,这是由于 Apple 对运行时做了大量优化(比如汇编级别快速路径、ISA-optimized fast path)来避免频繁进入 C 层函数。

1.对于非NSObject类, objc_msgSend是汇编函数,非普通 C 函数

  • 它大多数时候在汇编层 直接查找 IMP 并跳转执行,不会进入 Objective-C runtime 的 C 函数实现。

  • 也就是说,objc_msgSend(obj, @selector(alloc)) 通常直接跳到了元类中的 +alloc 的 IMP。(这里涉及到后面cache_t的方法缓存,如果命中了Cache,就不会走完整的流程)

  1. 对于NSObject, 是基础类,系统做了特殊优化

  • 对于 NSObject和一些常见类,Apple 使用了 汇编级别的 fast path,这意味着即便你打断点试图进入 _objc_rootAlloc,你可能根本进不去。

  • 常见的“未命中源码”的情况说明使用的是缓存或特殊入口。

alloc的调用流程

通过调用alloc后的堆栈详情我们就可以发现,无论是NSObject类还是自定义类,调用alloc方法最开始走的都是objc_alloc而不是objc_rootAlloc。这是因为消息转发时系统在底层帮我们转发到了objc_alloc。我们来看看objc_alloc的源码实现

可以发现其实他和objc_rootAlloc的实现是一样的,调用callAlloc。

回顾之前callAlloc的实现

可以看到callAlloc中分为几个分支来处理

对于NSObjcet类,初始化在llvm编译时就已经初始化好了,因此缓存中已经有alloc/allocWithZone方法了,hasCustomAWZ()为false,那么!cls->ISA()->hasCustomAWZ()就为true。

因此NSObjcet在此时会进入_objc_rootAllocWithZone并调用_class_createInstanceFromZone,后面的步骤就和之前说的一样了,这就是为什么NSObjct没有走alloc方法

而对于自定义类,初次创建时没有默认的alloc/allocWithZone实现,所以继续向下执行进入到消息发送流程,消息转发时会向父类找,最终找到NSObjcet的alloc并调用,即[NSObjcet alloc],这时会来到_objc_rootAlloc,进入后再次调用callAlloc,这次调用的是NSObject类的,缓存中存在alloc/allocWithZone实现,就接着走_objc_rootAllocWithZone方法,后面步骤也就和之前一样了。所以自定义类在调用alloc时会走两次callAlloc

总结一下,NSObjcet的调用链如下图:

自定义类的调用链如下图:

http://www.xdnf.cn/news/467515.html

相关文章:

  • 【办公类-100-01】20250515手机导出教学照片,自动上传csdn+最大化、最小化Vs界面
  • AD PCB板logo及二维码放置
  • Linux基础 -- 在内存中使用chroot修复eMMC
  • 非加密散列算法的应用-MurmurHash
  • 【Java】Spring IoC中的相关注解
  • 关于mysql分区键
  • Web GIS可视化地图框架Leaflet、OpenLayers、Mapbox、Cesium、ArcGis for JavaScript
  • 5.15本日总结
  • docker 命令操作大全
  • 【Matlab】最新版2025a发布,深色模式、Copilot编程助手上线!
  • redis中key的过期和淘汰
  • PDA手持终端应用有哪些?
  • Python生成器:高效处理大数据的秘密武器
  • YOLO11解决方案之距离计算探索
  • RHCE实验:通过脚本判断用户是否存在
  • 与entity物体的交互
  • 提升MySQL运维效率的AI利器:NineData深度评测与使用指南
  • 网页渲染的两条赛道
  • 语音识别——语音转文字
  • 20250515通过以太网让VLC拉取视熙科技的机芯的rtsp视频流的步骤
  • Spring Boot 拦截器:解锁5大实用场景
  • QImage高效率像素操作的方法
  • 基于windows环境Oracle主备切换之后OGG同步进程恢复
  • 兰亭妙微B端UI设计:融合多元风格,点亮品牌魅力
  • 嵌软面试每日一阅----通信协议篇(二)之TCP
  • 一招解决Tailwindcss4.x与其他库样式冲突问题
  • 报销单业务笔记
  • 中国近代史2
  • 深度学习框架对比---Pytorch和TensorFlow
  • MySQL 学习(十)执行一条查询语句的内部执行过程、MySQL分层