首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >目标C消息分发机制

目标C消息分发机制
EN

Stack Overflow用户
提问于 2009-06-11 16:21:20
回答 2查看 20K关注 0票数 65

我只是在玩Objective (编写玩具iPhone应用程序),我很好奇用来发送消息的底层机制。我非常了解C++中的虚拟函数是如何实现的,以及与静态或非虚拟方法调用相关的成本,但我不了解Obj是如何发送消息的。在浏览时,我发现是一个松散的基准测试,它提到IMP缓存的消息比虚拟函数调用更快,而虚拟函数调用又比标准消息发送更快。

我没有试图优化任何东西,只是更深入地了解消息是如何被发送的。

  • Obj消息是如何发送的?
  • 实例方法指针是如何被缓存的,您(通常)如何通过读取代码来判断消息是否会被缓存?
  • 类方法与C函数(或C++中的静态类方法)本质上是相同的,还是有更多的东西?

我知道其中一些问题可能是“实现依赖的”,但是只有一个实现是真正重要的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-06-11 17:05:39

如何发送Obj消息?

Objective消息是使用运行时的objc_msgSend()函数发送的。如苹果文档所示,该函数至少包含2个参数:

  1. 接收对象
  2. 消息的选择器
  3. 发送消息的参数的变量列表。

类的实例有一个isa指针,它是指向其类对象的指针。每个对象中的方法选择器存储在类对象中的“表”中,objc_msgSend()函数遵循指向类对象的isa指针,查找此表,并检查方法是否在类的表中。如果它找不到它,它将在类的超类的表中查找方法。如果未找到,则继续在对象树上运行,直到找到方法或获取根对象(NSObject)为止。此时,将引发异常。

实例方法指针是如何被缓存的,您(通常)如何通过读取代码来判断消息是否会被缓存?

摘自苹果公司关于消息传递的Objective运行时指南

为了加快消息传递过程,运行时系统缓存方法的选择器和地址。每个类都有一个单独的缓存,它可以包含继承方法和类中定义的方法的选择器。在搜索分派表之前,消息传递例程首先检查接收对象类的缓存(理论是可能再次使用曾经使用过的方法)。如果方法选择器在缓存中,则消息传递仅略慢于函数调用。一旦一个程序运行足够长的时间来“预热”它的缓存,它发送的几乎所有消息都会找到一个缓存的方法。当程序运行时,缓存动态增长以容纳新消息。

如前所述,缓存在程序运行后就开始发生,并且在程序运行足够长时间之后,大多数方法调用都将通过缓存的方法运行。正如它还指出的,缓存是在使用方法时发生的,因此只有在使用消息时才会缓存消息。

是类方法,本质上与C函数(或C++中的静态类方法)相同,或者它们还有更多的东西吗?

类对象以类似于类实例的方式处理方法发送。每个类对象都有一个对象,它将自己的类方法存储在一个名为metaclass的对象中。类对象有自己的元类对象的isa指针,而元类对象又有超级元类对象,可以从这些对象继承类对象。方法分派到类方法如下:

  1. 分派系统遵循类对象指向元类对象的isa指针
  2. 在元类对象的方法表中搜索类方法。
  3. 如果找不到,搜索将继续到元类对象的超类,在那里继续搜索。
  4. 此过程会一直重复,直到找到该方法,或直到它到达根元类,并引发异常。
票数 103
EN

Stack Overflow用户

发布于 2021-12-03 17:53:12

调度机制

它用于在调用方法(发送消息)时找到必要的可执行代码。

  • Inline
  • Static(Direct)(C,Java final,C++ default,Swift staticfinal) -编译器知道在编译时实现必要的方法。
  • Dynamic -是基于witness table(虚拟表,调度表)的,并引入了多态性。
    • Table,V- table (C++ virtual,Java,Swift默认值)--每个对象都有一个类的引用,它有一个具有所有方法地址的表(超级、重写、新的)。SIL包含vtablewitness_table
    • Message(object,Swift dynamic) -每个对象都有一个对的引用(Isa),其中包含对超类调度表E 232的引用(它只包含已实现的方法(新的和开销的)),而不包含来自Super的方法。如果在当前调度表中没有找到方法,则继续在超类的调度表中搜索。通过缓存优化了这个过程。SIL包含volatile目标-C消息分发

例如

代码语言:javascript
复制
class A {
    func foo1() {}
    func foo2() {}
}

class B: A {
    override func foo2() {}
    func foo3() {}
}

目标C obc_msgSend

代码语言:javascript
复制
id obc_msgSend(id self, SEL op, ...)
// self - object which receive a message
// op - selector of method
//... - arguments

如果没有为给定的选择器找到方法实现,则会看到下一个错误。

代码语言:javascript
复制
unrecognized selector sent to instance
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/982116

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档