区块链技术博客
www.b2bchain.cn

大师重磅内容(15)-Runtime运行时&方法的本质求职学习资料

本文介绍了大师重磅内容(15)-Runtime运行时&方法的本质求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

运行时和编译时

  • 编译时:顾名思义就是正在编译的时候,编译时简单的作⼀些翻译⼯作,⽐如检查关键字是否错误,词法分析,语法分析之类的过程。

  • 运行时:就是代码跑起来了,被装载到内存中去了。如果出现错误会导致程序崩溃。

Runtime调用的三种途径

大师重磅内容(15)-Runtime运行时&方法的本质

  • Objective-C Code代码中,比如对象方法的调用, [user sayHello];;
  • Framework&Service中,接口的调用,比如isKindOfClassisMemberOfClass等;
  • Runtime API中,c/c++源码方法的使用,比如objc_msgSendobjc_msgSendSuper

上图中:

  • Compiler为编译器层,会将代码翻译成某个中间状态的语⾔,同时会做一些LLVM编译器的优化,比如将alloc方法优化执行objc_alloc方法。
  • runtime system libarary 就是底层库。

方法调用的本质

使用clangoc代码编译成c/c++代码,查看本质。
((void (*)(id, SEL))(void *)objc_msgSend)((id)user, sel_registerName("sayHello"));

Objective-C中,user对象的sayHello方法的调用,最终是通过c/c++objc_msgSend来实现。objc_msgSend很眼熟,因为我们在上一篇章,cache_t结构分析与底层探索中,发现过他的踪迹!

回顾一下我们探索cache_t的思路和流程:
思路:决定一个类功能的是函数,所以从cache_t的函数中去寻找突破口

  • cache_t结构体中,有一个方法void incrementOccupied();,增加占用,内部实现为:_occupied++;,很容易理解:向cache_t中插入内容,占用数加1

  • 全局搜索incrementOccupied()方法,只有一个地方用到了该方法,向cache_t中插入数据,cache_t::insert方法。

  • 继续全局搜索cache_t::insert方法找到了一段非常重要的注释,解读注释:cache_t分为cache读取和cache写入两个点。见下图:

大师重磅内容(15)-Runtime运行时&方法的本质

这里给了我们很大的启发,结合上面的分析,方法的调用最终都是转为了消息发送,也就是objc_msgSend,此过程中应该会通过cache_getImp方法从缓存cache_t中获取方法实现,从而完成方法的一个查找流程,最终完成函数的执行。

将OC代码做个转换,使用objc/message.h c/c++源码来实现方法调用。例如:

GFPerson * user = [GFPerson alloc]; [user sayHello]; objc_msgSend(user, sel_registerName(@"sayHello"));

运行发现调用结果是一致的。需要注意的是需要将objc_msgSend严厉的检查机制关掉。见下图:

大师重磅内容(15)-Runtime运行时&方法的本质

如果 Son继承自FatherSon只进行了sayHello方法的声明,并没有实现sayHello方法,father实现了sayHello方法。在main中,Son调用了方法sayHello。参考下面的示例:

“`c
@interface Father : NSObject
-(void)sayHello;
@end
@implementation Father
-(void)sayHello{
NSLog(@”sayHello %s”, __func__);
}

运行时和编译时

  • 编译时:顾名思义就是正在编译的时候,编译时简单的作⼀些翻译⼯作,⽐如检查关键字是否错误,词法分析,语法分析之类的过程。

  • 运行时:就是代码跑起来了,被装载到内存中去了。如果出现错误会导致程序崩溃。

Runtime调用的三种途径

大师重磅内容(15)-Runtime运行时&方法的本质

  • Objective-C Code代码中,比如对象方法的调用, [user sayHello];;
  • Framework&Service中,接口的调用,比如isKindOfClassisMemberOfClass等;
  • Runtime API中,c/c++源码方法的使用,比如objc_msgSendobjc_msgSendSuper

上图中:

  • Compiler为编译器层,会将代码翻译成某个中间状态的语⾔,同时会做一些LLVM编译器的优化,比如将alloc方法优化执行objc_alloc方法。
  • runtime system libarary 就是底层库。

方法调用的本质

使用clangoc代码编译成c/c++代码,查看本质。
((void (*)(id, SEL))(void *)objc_msgSend)((id)user, sel_registerName("sayHello"));

Objective-C中,user对象的sayHello方法的调用,最终是通过c/c++objc_msgSend来实现。objc_msgSend很眼熟,因为我们在上一篇章,cache_t结构分析与底层探索中,发现过他的踪迹!

回顾一下我们探索cache_t的思路和流程:
思路:决定一个类功能的是函数,所以从cache_t的函数中去寻找突破口

  • cache_t结构体中,有一个方法void incrementOccupied();,增加占用,内部实现为:_occupied++;,很容易理解:向cache_t中插入内容,占用数加1

  • 全局搜索incrementOccupied()方法,只有一个地方用到了该方法,向cache_t中插入数据,cache_t::insert方法。

  • 继续全局搜索cache_t::insert方法找到了一段非常重要的注释,解读注释:cache_t分为cache读取和cache写入两个点。见下图:

大师重磅内容(15)-Runtime运行时&方法的本质

这里给了我们很大的启发,结合上面的分析,方法的调用最终都是转为了消息发送,也就是objc_msgSend,此过程中应该会通过cache_getImp方法从缓存cache_t中获取方法实现,从而完成方法的一个查找流程,最终完成函数的执行。

将OC代码做个转换,使用objc/message.h c/c++源码来实现方法调用。例如:

GFPerson * user = [GFPerson alloc]; [user sayHello]; objc_msgSend(user, sel_registerName(@"sayHello"));

运行发现调用结果是一致的。需要注意的是需要将objc_msgSend严厉的检查机制关掉。见下图:

大师重磅内容(15)-Runtime运行时&方法的本质

如果 Son继承自FatherSon只进行了sayHello方法的声明,并没有实现sayHello方法,father实现了sayHello方法。在main中,Son调用了方法sayHello。参考下面的示例:

“`c
@interface Father : NSObject
-(void)sayHello;
@end
@implementation Father
-(void)sayHello{
NSLog(@”sayHello %s”, __func__);
}

运行时和编译时

  • 编译时:顾名思义就是正在编译的时候,编译时简单的作⼀些翻译⼯作,⽐如检查关键字是否错误,词法分析,语法分析之类的过程。

  • 运行时:就是代码跑起来了,被装载到内存中去了。如果出现错误会导致程序崩溃。

Runtime调用的三种途径

大师重磅内容(15)-Runtime运行时&方法的本质

  • Objective-C Code代码中,比如对象方法的调用, [user sayHello];;
  • Framework&Service中,接口的调用,比如isKindOfClassisMemberOfClass等;
  • Runtime API中,c/c++源码方法的使用,比如objc_msgSendobjc_msgSendSuper

上图中:

  • Compiler为编译器层,会将代码翻译成某个中间状态的语⾔,同时会做一些LLVM编译器的优化,比如将alloc方法优化执行objc_alloc方法。
  • runtime system libarary 就是底层库。

方法调用的本质

使用clangoc代码编译成c/c++代码,查看本质。
((void (*)(id, SEL))(void *)objc_msgSend)((id)user, sel_registerName("sayHello"));

Objective-C中,user对象的sayHello方法的调用,最终是通过c/c++objc_msgSend来实现。objc_msgSend很眼熟,因为我们在上一篇章,cache_t结构分析与底层探索中,发现过他的踪迹!

回顾一下我们探索cache_t的思路和流程:
思路:决定一个类功能的是函数,所以从cache_t的函数中去寻找突破口

  • cache_t结构体中,有一个方法void incrementOccupied();,增加占用,内部实现为:_occupied++;,很容易理解:向cache_t中插入内容,占用数加1

  • 全局搜索incrementOccupied()方法,只有一个地方用到了该方法,向cache_t中插入数据,cache_t::insert方法。

  • 继续全局搜索cache_t::insert方法找到了一段非常重要的注释,解读注释:cache_t分为cache读取和cache写入两个点。见下图:

大师重磅内容(15)-Runtime运行时&方法的本质

这里给了我们很大的启发,结合上面的分析,方法的调用最终都是转为了消息发送,也就是objc_msgSend,此过程中应该会通过cache_getImp方法从缓存cache_t中获取方法实现,从而完成方法的一个查找流程,最终完成函数的执行。

将OC代码做个转换,使用objc/message.h c/c++源码来实现方法调用。例如:

GFPerson * user = [GFPerson alloc]; [user sayHello]; objc_msgSend(user, sel_registerName(@"sayHello"));

运行发现调用结果是一致的。需要注意的是需要将objc_msgSend严厉的检查机制关掉。见下图:

大师重磅内容(15)-Runtime运行时&方法的本质

如果 Son继承自FatherSon只进行了sayHello方法的声明,并没有实现sayHello方法,father实现了sayHello方法。在main中,Son调用了方法sayHello。参考下面的示例:

“`c
@interface Father : NSObject
-(void)sayHello;
@end
@implementation Father
-(void)sayHello{
NSLog(@”sayHello %s”, __func__);
}

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 大师重磅内容(15)-Runtime运行时&方法的本质求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们