23

Runtime数据结构详解

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUyMDAxMjQ3Ng%3D%3D&%3Bmid=2247493189&%3Bidx=1&%3Bsn=8d14ff2d06513cc286ee48ae9edf4862
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

我们先看Runtime整体的数据结构如下图:

IJVvUvU.jpg!web

初识objc_object

我们平时用到的所有的对象都是id类型,而id对象在runtime中都被定义为objc_object 的结构体。

objc_object的结构体中定义中包含以下五个部分:

1、 isa_t类型的isa

UVjURrb.jpg!web

2、 isa操作相关

nUbIf2I.jpg!web

3、 弱引用相关方法-可以标记改对象是否包含一些弱引用

ERfQfa6.jpg!web

4、 关联对象相关方法-标记该对象是否有一些关联对象

RV7za2i.jpg!web

5、 内存管理相关方法-我们平时使用的和内存相关的方法

myINvuA.jpg!web

*注:详细的定义可以在Runtime源码编译后工程的Project Headers文件夹下,objc-private.h文件中查看关于objc_objc结构体的定义。

什么是objc_class

在OC语言中的Class对应的Runtime里objc_class, 下图为objc_class的定义,从图中我们也可以看出objc_class继承于objc_object,即objc_class中也含有一个isa指针,并且继承了objc_object的相关的方法及函数。所以我们定义的类也可以被看作是一个对象。 

Qvyumer.jpg!web

截图中我们只截了重要的定义忽略了一系列的函数,如果想要查看,可以在Runtime源码编译后工程的Project Headers文件夹下objc-runtime-new.h中查看所有的方法。

而本文我们主要讲下最重要的三个数据成员。

1. Class superclass : Class类型,表示当前类的父类。

2. cache_t cache : 方法缓存的结构,在消息传递过程中会被用到。用于优化方法调用,提高性能。其数据结构实际上是一个可增量扩展的哈希表,用来缓存我们调用频次较高的函数。这个哈希表中存放的是bucket_t,而bucket_t中包含了key、IMP,key为方法名,而IMP我们可以将其理解为函数指针,这样在执行方法的时候我们拿到方法名就可以快速的查找到对应的执行函数指针。下图为cache_t及bucket_t的具体定义,同样可以在objc-runtime-new.h中找到。

qUryAvV.jpg!web

EzEBbmY.jpg!web

3. class_data_bits_t bits : 类结构中的核心部分,它的作用类似于优化过的isa指针,下文中会再详细。 

class_data_bits_t bits

class_data_bits_t bits只含有一个成员uintptr_t bits,uintptr_t实际上是unsigned long类型,在arm64为8字节(64位),我们可以将uintptr_t bits理解为一个64位的存储域,里面存储的不仅包含指针,而且可以同时包含类的一些信息,这些信息通过对应的掩码获取,比如在类结构中非常重要的class_rw_t*就是通过(bits & FAST_DATA_MASK)来获取,具体见struct class_data_bits_t内部的data()函数。

F7vyuui.jpg!web

下面我们来看下class_rw_t是个什么呢?

class_rw_t定义

fMBvuyi.jpg!web

截图中我们省略了函数,省略部分同样可以在objc-runtime-new.h中找到

从截图中我们可以看到最重要的数据结构有:

1、 class_ro_t *ro下面再分析这个数据结构。

2、 method_array_t method;方法列表。

3、 property_array_t properties;属性。

4、 protocol_array_t protocols;协议。

5、 firstSubclass、nextSiblingClass与继承相关的指针。

6、 demangledName Class对应的符号名称。

class_ro_t  *ro常量指针

该指针指向的内容是只读不可修改的。关于class_ro_t的定义可以参见下图:

ZBRrIj2.jpg!web

需要我们关注的主要是:

* name 函数名

* baseMethodList 方法列表

* baseProtocols 协议

* ivars 类的成员变量

* baseProperties属性

其中method_list_t是一个数组包含了多个method_t,而method_t就是我们平常使用的函数,其结构体包括:

* 名称

* 返回值类型

* 函数体

* 参数如下图:

mqmUBru.jpg!web

总结:本文主要介绍了我们平常OC中使用的对象、类以及类中的方法在runtime中的定义及数据结构,关于runtime源码的编译可参见下边的Runtime源码编译链接。

ENNZnaR.png!web

参考文章链接

Runtime源码编译链接:

https://mp.weixin.qq.com/s/hfwZiKt4D46gg9GOg1ZOsw

https://blog.csdn.net/u013378438/article/details/80493158

https://www.jianshu.com/p/75c0d214dc8b

https://www.jianshu.com/p/13457a27624c


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK