方法的消息查找流程

457 阅读2分钟

我们上次分析cache_t ,它是用来缓存方法,方法调用cache_t首先查看自身有没有相应的缓存,没有的话进行缓存填充

方法查找流程:

那么方法又是如何调用的呢,换句话说,我当我们第一次调用方法时,底层又是如何查找并实现的?下面我们进行分析:

我们定义代码通过汇编查找最终定位于

 LLGirlStu *stu = [[LLGirlStu alloc]init];
        [stu study];


简单的看这句话的含义就是方法的寻找和加载在 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,我从里面找了两段重要的代码择了出来


这段是自身方法进行查找,找到后进行log_and_fill_cache()方法缓存

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


这段则是在其父类中进行查找,同样找到后进行log_and_fill_cache()方法缓存

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;
}
}


崩溃浅述

那么如果自身和父类都找不到怎么办?则是这样的也就是我们普通的崩溃


查找流程基本就是这样,看着很多,其实流程走的很简单,(流程不多,贴的图有点多 笑哭.jpg)


附图:

附简单的查找流程图: