美文网首页
01--方法本质05--消息查找流程

01--方法本质05--消息查找流程

作者: 修_远 | 来源:发表于2020-06-15 16:59 被阅读0次

    对方法的探索,全篇分六个章节

    01-方法本质-方法初探

    02-方法本质-objc_msgSend的使用

    03-方法本质-面试题分析

    04-方法本质-lookUpImpOrForward 介绍

    05-方法本质-消息查找流程

    06-方法本质-消息转发流程

    五、消息查找流程(重点)

    前言

    这一章将会介绍消息的第一个流程——查找流程。

    当调用一个方法的时候,系统是从哪里找到这个方法的?

    [toc]

    5.1 lookUpImpOrForward 准备条件

    从源码中可以看到,有一个 retry:,retry的意思是重试,那么可以猜测出来下面的才是正真的流程,那上面的内容是什么呢?

    retry上面的两段代码,_class_initializerealizeClass,不是初始化就是准备,可以猜测这里是一些变量的准备条件

    再往上面走,看到有一个 runtimeLock。lock(); 方法,而且还有很多注释,说明这段代码在这个方法里面有很重要的作用。仔细扒一扒这些注释的含义,

    • 注释一:讲了运行时锁的作用,防止多线程发生资源抢夺

      runtimeLock在isrealize和isInitialized检查过程中被持有,以防止对并发实现的竞争。

    • 注释二:讲了为什么要添加运行时锁。举了一个例子,在缓存中搜索方法的时候(读操作),分类可以刷新缓存(写操作),同时对一块内存进行读写操作,它是受不了的。

      runtimeLock在方法搜索过程中保持,使方法查找+缓存填充原子相对于方法添加。否则,可以添加一个类别,但是会无限期地忽略它,因为在代表类别的缓存刷新之后,缓存会用旧值重新填充。

    继续往上面走,有一个 return imp; 代码。这个方法本来就是查找一个方法的,能 return 的话,说明这个方法找到了。这里的代码很简单,就是从缓存里面找到了方法。

    有趣的是这段代码的注释--// Optimistic cache lookup(乐观的缓存查找)。这就有意思了,什么叫乐观的,我们程序员讲究的是严谨的,要么能找到要么不能找到,既然是乐观的,我们就不用去分析他了。

    再往上面走就是一些变量的创建,没什么好分析的。

    到这里,我们对 lookUpImpOrForward 方法已经分析了一半了,下面来看另外一半流程。

    5.2 lookUpImpOrForward 查找流程

    5.2.1 lookUpImpOrForward 流程图

    image

    5.2.2 lookUpImpOrForward 流程分析

    retry 开始分析

    1、从类的缓存查找,如果找到IMP,则跳到Done,返回IMP
    imp = cache_getImp(cls,sel);

    2、从类的方法列表查找
    Method meth = getMethodNoSuper_nolock(cls,sel);

    • 查找算法:二分查找
    • 如果找到,则填充缓存,跳到Done,返回IMP
      log_and_fill_cache(cls,meth->imp,sel,inst,cls);

    遍历父类

    for (Class curClass = cls->superclass;
                  curClass != nil;
                  curClass = curClass->superclass)
    

    3、从父类的缓存查找
    imp = cache_getImp(curClass,sel);

    • 如果在父类中找到方法,则将方法缓存到当前类,下次可以直接从缓存取
    • 跳到Done,返回IMP
      log_and_fill_cache(cls,imp,sel,inst,curClass);

    4、从父类的方法列表查找
    Method meth = getMethodNoSuper_nolock(curClass,sel);

    • 查找算法:二分查找
    • 如果找到,则填充缓存
    • 跳到Done,返回IMP
      log_and_fill_cache(cls,meth->imp,sel,inst,curClass);

    5、方法动态决议流程
    _class_resolveMethod(cls,sel,inst);

    6、消息转发流程
    imp = (IMP)_objc_msgForward_impcache;

    5.3 总结

    1. 为什么分析 lookUpImpOrForward 方法。
    2. 怎么分析 lookUpImpOrForward 方法。
    3. retry 前做了什么事。
    4. retry 后的流程是什么样的。
    5. lookUpImpOrForward 查找流程图

    相关文章

      网友评论

          本文标题:01--方法本质05--消息查找流程

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