美文网首页IOSRuntime
Objective-C中Runtime的结构

Objective-C中Runtime的结构

作者: 成博 | 来源:发表于2017-02-11 20:23 被阅读0次

    Objective-C isa 指针 与 runtime 机制 这篇文章中详述了OC中Runtime的结构,附下图,

    每个 类 都有一对儿objc_class结构体:存储实例相关内容的结构体和存储类相关内容的结构体(meta),

    方便起见姑且把前者称之为Oclass,后者称之为Mclass吧,Oclass中的isa指向Mclass

    这里只是简单介绍下就不多做赘述,重点要说的是Instance of class的结构,也算是对那篇文章的一个补充,

    那篇文章中介绍了OC中Runtime结构组成,但没有说明创建实例时的结构和实例变量存储在哪里,

    如上图,创建一个实例时,只创建一个Instance(objc_object结构体),然后其中isa指针指向系统中唯一的一对儿objc_class,但是我们可以看到objc_object结构体中只有一个isa指针,那么它的实例变量存储在那里呢?下面会详细介绍

    下面是源码中的objc_class该结构体:

    struct objc_class {

    Class isa  OBJC_ISA_AVAILABILITY;

    Class super_class                                        OBJC2_UNAVAILABLE;

    const char *name                                        OBJC2_UNAVAILABLE;

    long version                                            OBJC2_UNAVAILABLE;

    long info                                                OBJC2_UNAVAILABLE;

    long instance_size                                      OBJC2_UNAVAILABLE;

    struct objc_ivar_list *ivars                            OBJC2_UNAVAILABLE;

    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;

    struct objc_cache *cache                                OBJC2_UNAVAILABLE;

    struct objc_protocol_list *protocols                    OBJC2_UNAVAILABLE;

    } OBJC2_UNAVAILABLE;

    每alloc一个实例的时候,会生成一个objc_object结构体如下,其中isa指向Oclass,Object就是一个objc_object

    struct objc_object {

    Class isa  OBJC_ISA_AVAILABILITY;

    };

    所有的实例方法地址都存储在Oclass的methodLists中,类方法地址在Mclass的methodLists中,调用实例内容就是在Oclass中寻径,调用类内容则在Mclass中寻径。

    现在要说最关键的了:实例所拥有的变量存储在哪里呢?(这个问题官档没细说,其它介绍Runtime的文章也没提)

    因为每个类在运行时只存在唯一一对儿Oclass和Mclass,可以看到objc_class中有个ivars,好像是存这里,但是实例变量是每个实例自有的啊!难道所有的objc_object的的实例变量都存在系统当中唯一的Oclass中吗?这是不合理的,讲道理的话实例变量应该存在objc_object当中才对,但是objc_object中只有一个isa指针,并没有地方去存变量。

    源码里可以发现,ivars中存的是一个叫偏移量的东西,这个偏移量记载了实例变量存储的位置相对于objc_object的偏移量。所以获取实例变量的过程就是,先通过objc_object的isa指针找到Oclass,然后获取ivars中该实例变量存储位置相对于objc_object存储地址的偏移量,然后沿着objc_object的地址偏移个位置找到该实例。

    这样的结构就解决了唯一一对儿objc-class对应无数个objc-object的问题。

    但同样带了的缺陷就是开创一个objc-object时,就要对它在内存中的布局安排好,为它后面的实例变量预留空间,如果这个实例的某些变量压根儿没用到,即使不被赋值,它依旧占用着空间。(不知道apple有没有对这个做一些类似内存映射的技巧优化解决这个问题)。

    相关文章

      网友评论

        本文标题:Objective-C中Runtime的结构

        本文链接:https://www.haomeiwen.com/subject/uuyoittx.html