IOS

iOS objc_msgSend 流程

2020-09-19  本文已影响0人  我要当个程序员

准备

Runtime吐槽

其实到现在我都不太能理解Runtime是什么,只能通俗的理解为:运行时。找了好几篇文档进行对比,什么静态语言,动态语言,我甚至也找了静态,动态语言的博客通读了一下。真的是一堆乱七八糟,都是复制粘贴+翻译来的吧!!

没办法,只能强制理解了,iOS里面的Runtime其实就是一些特别c/c++的api函数,用来装b。至于他有什么b用,我不知道,等我后面学习到了,在补上。

objc_msgSend是什么

objc_msgSend就是我所说Runtime中一些特别c/c++的api函数,其定义在#import <objc/message.h>,那么为什么要研究它呢?

打开我们的准备好的项目工程,在LGPerson中写一个test01函数方法,然后在main.m中调用

int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        appDelegateClassName = NSStringFromClass([AppDelegate class]);

        LGPerson *p = [LGPerson alloc];
        [p test01];
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

通过clang将我们的main.m文件编译成底层c/c++文件,来查看

//main.m文件所在的终端中输入
xcrun -sdk iphonesimulator clang -rewrite-objc main.m 

这时候将会把我们的main.m编译成main.cpp,打开main.cpp并滑动到最底层

int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    /* @autoreleasepool */ 
        { __AtAutoreleasePool __autoreleasepool; 

        appDelegateClassName = NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class")));
        Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc"));
        ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("test01"));
    }
    return UIApplicationMain(argc, argv, __null, appDelegateClassName);
}

由此可见,Xocde将oc的代码编译成c/c++文件。而我们oc中的调用方法是通过底层objc_msgSend函数来执行。

objc_msgSend参数和调用

<objc/message.h>中可知

objc_msgSend("对象","SEL","参数"...)
objc_msgSend( id self, SEL op, ... )
LGPerson *p = [LGPerson alloc];

//这两个是相等的,你们可以自己试一下
[p test01];
objc_msgSend(p,sel_registerName("test01"));

objc_msgSend流程分析

打开我们的准备好的项目工程,苹果开发者为了快速,所以objc_msgSend的函数实现是通过汇编的方式来写的。

1.png

ENTRY汇编函数的实现进入,具体的里面的代码就不带大家看了,你们可以自己打开工程点击进去看,这里开始梳理一下objc_msgSend的流程

1、objc_msgSend( id self, SEL op, ... )
2、ENTRY _objc_msgSend
3、对消息接受者(self,sel)判断处理
4、taggedPointer 判断处理
5、CacheLookup查找混存
6、cache_t处理,bucket以及内存哈希处理
      6.1找不到递归下一个bucket
      6.2找到返回
      6.3遇到意外重试
      6.4找不到 JumpMiss
7、__objc_msgSend_uncached 找不到缓存imp
8、MethodTableLookup 到isa里的bits.data()去查找

这里有一份:详细objc_msgSend流程研究

上一篇下一篇

猜你喜欢

热点阅读