zoukankan      html  css  js  c++  java
  • iOS底层学习第一节:OC对象探索

    iOS底层学习第一节:OC对象探索
    一、OC对象alloc & init 做了什么?
    众所周知alloc是开辟内存,init是初始化,我们查看一下下图,p1,p2,p3三个对象为同一个内存空间,指针p1,p2,p3为不同的指针,一个指针8个字节。

    init是一个默认构造方法,我们可以复写它而提供不同的构造方法初始化对象,alloc是一个开辟内存的方法,通过debug我们可以查看调用栈发现它进入了一个objc_alloc方法,但是我们无法查看源码,这时候需要去网上下载runtime源码。

    二、查看alloc流程
    首先我们可以下载runtime源码并且让这个项目运行起来,KC老师就是厉害...好好学习,赶上他的一半。
    参考掘金:https://juejin.cn/post/6914265121183236104
    runtime源码下载地址:https://opensource.apple.com/tarballs/objc4/

    NSObjcet初始化流程: objc_alloc -> callAlloc -> _objc_rootAllocWithZone -> _class_createInstanceFromeZone

    Person初始化流程:objc_alloc -> callAlloc -> alloc ->_objc_rootAlloc ->callAlloc ->_objc_rootAllocWithZone -> _class_createInstanceFromeZone

    这个流程调用栈其实并不重要,重要的是_class_createInstanceFromeZone方法中的三个方法分别是:计算对象内存大小,开辟对象内存大小,绑定对象的isa

    引入一个问题:为什么NSObjcet没有走alloc方法,而Person走了alloc->_objc_rootAlloc方法?
    解答:注意细节fastpath(!cls->ISA()->hasCustomAWZ())这个判断语句,如果存在isa,则直接走_objc_rootAllocWithZone,这个时候NSObjcet是存在isa的(之前就已经被初始化过,因为是所有的对象的父类);猜测第一次alloc的对象去自己的_objc_rootAlloc方法会有一些奇怪操作,之后重复调用alloc会去判断fastpath(!cls->ISA()->hasCustomAWZ())(会在LLVM中有这部分优化操作导致这个判断是true),然后直接去_objc_rootAllocWithZone初始化

    三、_class_createInstanceFromeZone三个方法的作用

    (网上找的图,侵删)

    前文可知三个方法分别为计算对象内存大小,开辟对象内存大小,绑定对象isa
    说到isa,这里拓展一个objc_class(objc1使用,现在已经废除),如下图,所有的对象都是结构体,对象的结构体objc_object只有isa和属性,类和元类都是使用objc_class这个结构体

    • isa指向类控件
    • super_class是父类class
    • name,version,info就是一些信息
    • instance_size是对象的大小
    • ivars是属性列表
    • methodLists是方法列表
    • cache是已经缓存的方法地址
    • protocols是协议列表

    instanceSize方法
    初始化内存大小,引入内存对齐概念:在iOS中,对象的最小单位为16字节,即使只存在isa(8字节)后面的8字节为空,这是因为macOS系统中读取是按照块来读,一块为16字节(系统升级提高效率),如果对象最小单位为8字节,则会读到其他对象内存,容易造成混乱。
    首先我们看一下结构体对齐的三个条件,结构体中如果属性顺序不同,相同属性的结构体可能最终需要的内存不一样。

    前面我们说过对象就是一个结构体,然而我们在写OC对象的时候却没有考虑属性的顺序,这是因为Clang在进行代码优化的时候直接选择了最优的结构体顺序(博客Clang与LLVM的关系 https://blog.csdn.net/baidu_24256693/article/details/79905396
    calloc方法
    开辟内存空间
    initInstanceIsa方法
    类对象和对象isa绑定

    四、isa介绍
    联合体位域
    前面我们提过isa只有8字节,也就是64位,但是这个isa里面却存放了很多的信息,使用位的01来表示BOOL的true,false,这就是联合体位域(我之前学习的时候有位图bitmap的叫法),在arm_64位系统的参考下,isa结构体定义如图

    简单介绍一下这里面的参数,其实有很多我也不认识...
    ISA_MASK:前面我们介绍,isa是一个联合体位域,只有中间33位才是真实的class对象,我们取出来对象的isa,然后& ISA_MASK就可以获得 Class 信息,如图我们调用类方法 getClass其实也就是取出来bits,然后&ISA_MASK

    Nonpointer:是否开启isa指针优化0代表纯isa指针,1代表isa优化
    Has_assoc:是否存在关联对象,释放内存不存在关联对象不需要释放减少消耗
    Has_xx_dtor:是否存在析构方法,释放内存不存在析构方法不调用减少消耗
    Shiftclass:转化的class,真实的类对象的地址
    Magic:⽤于调试器判断当前对象是真的对象还是没有初始化的空间
    Weakly_referenced:标志对象是否被指向或者曾经指向⼀个 ARC 的弱变量,
    没有弱引⽤的对象可以更快释放。
    Deallocating:标志对象是否正在释放内存
    Has_sidetable_rc:当对象引⽤技术⼤于 10 时,则需要借⽤该变量存储进位
    Extra_rc:当表示该对象的引⽤计数值,实际上是引⽤计数值减 1,
    例如,如果对象的引⽤计数为 10,那么 extra_rc 为 9。如果引⽤计数⼤于 10,
    则需要使⽤到下⾯的 has_sidetable_rc。

    Magic,Has_sidetable_rc,Extra_rc不是很懂(以后再看看吧)

    isa指向(简单介绍一下,下一个博客重点讲类)

    对象(instance)的isa指向类对象,类(class)对象的isa 指向元类(metaClass)对象
    对象的方法在类对象中,类方法在元类对象中
    Class(类)的superClass指向父类,rootClass(NSObject的类)的superClass指向nil
    metaClass(元类)的superClass指向父元类,metaClass(元类)的isa指向NSObject的元类
    NSObject的元类的isa指向他自己

  • 相关阅读:
    《需求工程-软件建模与分析之读书笔记之五》
    Neo4j (3.3.9)的学习之路(1)
    大数据培训第一天总结
    京东B2B业务架构演变阅读心得
    小米网抢购系统开发实践阅读心得
    余额宝技术架构及演进阅读心得
    美图数据统计分析平台架构演进阅读心得
    荔枝架构实践与演进历程阅读心得
    去哪儿网支付系统架构演进全历程阅读心得
    基于SOA质量属性的系统构架分析与实践
  • 原文地址:https://www.cnblogs.com/xzmxddx/p/14357692.html
Copyright © 2011-2022 走看看