Runtime底层原理分析
全栈老韩
全栈工程师,擅长iOS App开发、前端(vue、react、nuxt、小程序&Taro)开发、Flutter、React Native、后端(midwayjs、golang、express、koa)开发、docker容器、seo优化等。
OC对象、方法
- OC对象的本质是结构体;
- 方法的本质是消息发送;
- 消息的组成:
main.m
Person *p = [[Person alloc] init];
[p run];
本质:
main.mm
Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("new"));
((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("run"))
- 消息接收者:p
- 方法:
sel_registerName("run")-> 方法编号 -- 字符串name
通过sel 找到函数实现的指针.
函数实现类似于:
void runIMP(id self, SEL _cmd) {
...
}
Runtime调用的3种方式
- runtime api
- NSObject api isKindOf, isMemberOf
- 编译器提供的oc上层方法 @selector
- 向父类发消息
- 对象方法:
struct objc_super mySuper;
mySuper.receiver = s;
mySuper.super_class = class_getSuperclass([s class]);
objc_msgSendSuper(&mySuper, @selector(run));
- 类方法:
struct objc_super myClassSuper;
myClassSuper.receiver = [s class];
myClassSuper.super_class = class_getSuperclass(object_getClass([s class)); // 元类
objc_msgSendSuper(&myClassSuper, sel_registerName("walk"));
- 类方法存在元类之中,以实例方法的姿态形式存在
- 对象在类中是一个实例,类在元类中也是一个实例
objc_msgSend
- 快速
- 缓存找 汇编 -> cache_t 找imp通过hash表
- cache在类结构体中
- 慢速
直接通过C, C++, 汇编来找. 找到后存缓存
- objc_msgSend用汇编来写
- 如果用C函数,不能写一个函数,跳转到任意的指针
- C还要往下层编译,汇编快
- 汇编有寄存器, x0 - x31
源码分析
tagged pointer特殊的数据类型
- _objc_msgSend
- LNilOrTagged
- LGetIsaDone isa处理完毕
- CacheLoopup NORMAL
-
call imp
-
objc_msgSend_uncached
-
CacheHit
-
CheckMiss -> _objc_msgSend_uncached
-
add
additional: bl汇编指令就是跳转.
MethodTableLookup
C、C++:
- lookUpImpOrForward
- relizeClass(cls)
- _class_initialize
- 漫长的过程 -> 找方法 -> 找自己 -> 找父类 -> NSObject
-
getMethodNoSuper_nolock 递归查找方法列表中的方法
-
log_and_fill_cache
-
remap(cls)重映射
- resolver动态解析
如果方法没有实现,走resolver方法.
动态解析一次.
流程:
- lookup imp
- 如果没有,走_class_resolveMethod(只走一次)
- 如果不是元类,走_class_resolveInstanceMethod
- 如果是元类,走_class_resolveClassMethod,再_class_resolveInstanceMethod
- 消息转发forwardingTargetForSelector
- 方法签名
- 无法处理doesNotRecognize
查看所有的objc_msgSend信息的函数
extern void instrumentobjcMessageSends(BOOL);
可以在private -> tmp -> msgSends-进程号
总结
runtime就是可以做到
- 动态添加注册类
- 查询/添加属性、方法
- 等
发布于2024-01-29 15:10:42
浏览量72·
暂无评论,快来发表第一条评论吧