美文网首页
消息查找流程

消息查找流程

作者: 小溜子 | 来源:发表于2020-09-19 10:37 被阅读0次

上节我们分析了objc_msgSend的快速查找部分(汇编部分),这一节我们来分析其慢速部分,也就是c语言部分。

接下来我们通过在代码中打断点来跟进一下这个流程。

image.png

我们将断点的显示模式改为汇编显示。


image.png

然后将代码运行起来。


image.png
我们可以很清楚的看到,对象在调用方法时,底层是通过调用objc_msgSend函数来发送消息的,我们在objc_msgSend函数处打上断点,继续跟进去看看。
image.png
我们可以清楚的看到,objc_msgSend在缓存没有命中之后调用了_objc_msgSend_uncached。

_objc_msgSend_uncached

image.png

_objc_msgSend_uncached调用了_class_lookupMethodAndLoadCache3

_class_lookupMethodAndLoadCache3

通过上面的图片,我们可以清楚的看到_class_lookupMethodAndLoadCache3函数是存在于objc-runtime-new.mm:4845这个文件中。接下来我们来看看这个函数中都做了些什么。

IMP _class_lookupMethodAndLoadCache3(id obj, SEL sel, Class cls)
{
    return lookUpImpOrForward(cls, sel, obj, 
                              YES/*initialize*/, NO/*cache*/, YES/*resolver*/);
}

lookUpImpOrForward

在类对象的方法列表中查找IMP。

    {
        Method meth = getMethodNoSuper_nolock(cls, sel);
        if (meth) {
            log_and_fill_cache(cls, meth->imp, sel, inst, cls);
            imp = meth->imp;
            goto done;
        }
    }

如果没找到,继续在父类的缓存的方法列表中查找IMP。

{
        unsigned attempts = unreasonableClassCount();
        for (Class curClass = cls->superclass;
             curClass != nil;
             curClass = curClass->superclass)
        {
            // Halt if there is a cycle in the superclass chain.
            if (--attempts == 0) {
                _objc_fatal("Memory corruption in class list.");
            }
            
            // Superclass cache.
            imp = cache_getImp(curClass, sel);
            if (imp) {
                if (imp != (IMP)_objc_msgForward_impcache) {
                    // Found the method in a superclass. Cache it in this class.
                    log_and_fill_cache(cls, imp, sel, inst, curClass);
                    goto done;
                }
                else {
                    // Found a forward:: entry in a superclass.
                    // Stop searching, but don't cache yet; call method 
                    // resolver for this class first.
                    break;
                }
            }
            
            // Superclass method list.
            Method meth = getMethodNoSuper_nolock(curClass, sel);
            if (meth) {
                log_and_fill_cache(cls, meth->imp, sel, inst, curClass);
                imp = meth->imp;
                goto done;
            }
        }
    }

如果IMP没有找到,则尝试做一次动态方法解析。

    if (resolver  &&  !triedResolver) {
        runtimeLock.unlock();
        _class_resolveMethod(cls, sel, inst);//这里做一次动态方法解析。
        runtimeLock.lock();
        // Don't cache the result; we don't hold the lock so it may have 
        // changed already. Re-do the search from scratch instead.
        triedResolver = YES;
        goto retry;
    }

如果没有找到IMP,并且方法解析也没有处理,那么则进入消息转发流程。

// No implementation found, and method resolver didn't help. 
    // Use forwarding.

    imp = (IMP)_objc_msgForward_impcache;

总结

1.当在 objc_msgSend 缓存中没有找到方法,就会来到 class_lookupMethodAndLoadCache3 进行慢速查找流程。
2.在 lookUpImpOrForward 里面会先去本类当中查找方法 getMethodNoSuper_nolock,本类没有找到就会去递归的去父类当中查找。
3.如果本类和父类都没有找到,就会进行动态方法决议 _class_resolveMethod,这是苹果爸爸给我们的最后一次机会。
4.动态方法我们还不处理,最后就会走到 _objc_forward_handler,然后崩溃报错 selector sent to instance。

相关文章

  • 消息查找流程

    上节我们分析了objc_msgSend的快速查找部分(汇编部分),这一节我们来分析其慢速部分,也就是c语言部分。 ...

  • 消息查找流程

    iOS中方法的查找分为两部分: 快速查找,在缓存中直接找到发送的消息 慢速查找,在缓存中如果没找到就到了慢速查找,...

  • OC 消息转发流程分析

    上一篇消息查找流程 探索了消息查找流程:快速查找和慢速查找以及动态方法解析。但消息机制还不完整,如果动态方法解析之...

  • iOS 消息转发流程

    runtime方法查找流程及消息转发 方法查找 方法查找的流程:缓存查找-->当前类查找-->父类逐级查找 1.缓...

  • 消息查找流程-慢速查找流程

    上一篇文章Cache分析及objc_msgSend初探[https://www.jianshu.com/p/18b...

  • 消息转发流程

    消息转发机制 消息的查找流程分为:快速查找和慢速查找消息转发机制也分为:快速和慢速先来一个转发流程图 之前我们的消...

  • OC 消息查找流程

    上一篇 OC 方法的本质 中提到OC的方法调用依赖于runtime实现的api(objc_msgSend、obj...

  • iOS 消息查找流程

    在上次的objc_msgSend分析的文章中,我们得知,方法的本质就是调用objc_msgSend函数来发送消息。...

  • OC消息转发(三)— 动态方法解析和消息转发机制

    前言 前边两篇文章(objc_msgSend探索、消息的查找流程探索)我们对调用方法到消息的查找流程做了详细探索,...

  • 方法查找流程-慢速查找

    在消息查找流程-快速查找流程[https://www.jianshu.com/p/8cfaf39c4810],中分...

网友评论

      本文标题:消息查找流程

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