runtime浅谈(一)动态运行时和消息机制

最近听周围的朋友在讨论runtime,索性来研究一下,runtime是什么,原理又是什么。

总的来讲,runtime简称运行时,就是系统在运行的时候的一些机制,它是开源的。其中最关键的就是消息机制。

1、Objective-C 的 Runtime 是一个运行时库(Runtime Library),它是一个主要使用 C 和汇编写的库,为 C 添加了面相对象的能力并创造了 Objective-C这就是说它在类信息(Class information) 中被加载,完成所有的方法分发,方法转发,等等.然而对于C语言,函数的调用在编译的时候就会决定调用哪个函数。编译完成之后直接顺序执行。

2、Objective-C runtime 创建了所有需要的结构体,让 Objective-C 的面相对象编程变为可能。

3、Objective -C的函数调用为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个 函数, 消息只有到运行时才会和函数实现绑定起来,而不是按照编译好的逻辑一成不变的执行,这也是有可能造成程序崩溃的原因。

4、运行时系统通过Objective-C源码、NSObject方法和运行时系统的函数与runtime system进行交互。

本次我们只讨论有关消息的问题:

消息例子:
<span style="font-size:14px;">[obj makeText];</span>
其中obj是一个对象,makeText是一个函数名称。对于这样一个简单的调用。在编译时RunTime会将上述代码转化成
<span style="font-size:14px;">objc_msgSend(obj,@selector(makeText));</span>
iOS中的obj都继承于NSObject。
<span style="font-size:14px;">@interface NSObject <NSObject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}</span>
在NSObjcet中存在一个Class的isa指针。然后我们看看Class:
typedef struct objc_class *Class;
struct objc_class {
  Class isa; // 指向metaclass 
  Class super_class ; // 指向其父类
  const char *name ; // 类名
  long version ; // 类的版本信息,初始化默认为0,可以通过runtime函数class_setVersion和class_getVersion进行修改、读取
  long info; // 一些标识信息,如CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含对象方法和成员变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法;
  long instance_size ; // 该类的实例变量大小(包括从父类继承下来的实例变量);
  struct objc_ivar_list *ivars; // 用于存储每个成员变量的地址
  struct objc_method_list **methodLists ; // 与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储对象方法,如CLS_META (0x2L),则存储类方法;
  struct objc_cache *cache; // 指向最近使用的方法的指针,用于提升效率;
  struct objc_protocol_list *protocols; // 存储该类遵守的协议
    }

Class isa:指向metaclass,也就是静态的Class。一般一个Obj对象中的isa会指向普通的Class,这个Class中存储普通成员变量和对 象方法(“-”开头的方法),
普通Class中的isa指针指向静态Class,静态Class中存储static类型成员变量和类方法(“+”开头的方 法)。

@selector (makeText):这是一个SEL方法选择器。SEL其主要作用是快速的通过方法名字(makeText)查找到对应方法的函数指针,然后调用其函 数。SEL其本身是
一个Int类型的一个地址,地址中存放着方法的名字。对于一个类中。每一个方法对应着一个SEL。所以iOS类中不能存在2个名称相同 的方法,即使参数类型不同,因为
SEL是根据方法名字生成的,相同的方法名称只能对应一个SEL。

最后来看看具体消息发送之后是怎么来动态查找对应的方法的。

首先,编译器将代码[obj makeText];转化为objc_msgSend(obj, @selector (makeText));,在objc_msgSend函数中。首先通过obj的isa指针找到obj对应的class。在Class中先去cache中 通过SEL查找对应函数method(猜测cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度),若 cache中未找到。再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加 入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。


方法调用中的隐藏参数:

当objc_msgSend找到方法对应的实现时,它将直接调用该方法实现,并将消息中所有的参数都传递给方法实现,同时,它还将传递两个隐藏的参数:

1、接收消息的对象(也就是self指向的内容)

2、方法选标(_cmd指向的内容)


相关链接:

http://www.cocoachina.com/ios/20141018/9960.html

http://my.oschina.net/panyong/blog/298631

http://blog.csdn.net/wzzvictory/article/details/8624057


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值