Objective-C 运行时如何实例化根元类和其他类描述?

Posted

技术标签:

【中文标题】Objective-C 运行时如何实例化根元类和其他类描述?【英文标题】:How does the Objective-C runtime instantiate the root metaclass and other class descriptions? 【发布时间】:2011-01-14 05:44:23 【问题描述】:

我正在尝试实现一个基本的面向对象的 ANSI C 运行时并使用 Objective-C 作为指南。

它们似乎是三个部分。类描述、类接口和类实现。为了实例化 Class Interface,使用 Class 对象实例化对象的熟悉方法只有在运行时已经使用类描述实例化您的类对象时才会发生。

那么所有类定义在第一次运行时都是静态分配的,以提供使用类对象实例化的能力吗?或者如果它们是动态分配的(在初始调用时),如何分配?它是运行循环的一部分,还是 Class 实际上是一个函数,在转发消息之前确定它是否已经分配?

【问题讨论】:

【参考方案1】:

运行时通过在实际程序执行之前调用的构造函数进行一些初始化。他们在 gcc 和 clang 中都是 __attribute__((constructor))

在 Objective-C 的情况下,其中一些被编译器嵌入到二进制文件中。您必须将它们包含在您的标题中以获得类似的效果。

这些函数使用编译器自动嵌入的数据。他们做一些事情,例如为类查找函数构建哈希表,然后将其用于实际的消息传递。

另一方面,实例是动态分配的。

我正在做类似的事情,所以我真的不知道比这更好,但这就像我挖的一样深。

【讨论】:

因此,编译器内部的 Obj-C 词法分析器从您的接口(.h 文件)生成通用类描述,将列表存储在哈希表中以进行类查找,但触发初始化的原因是提到的构造函数?不需要在 main 中调用某些东西来设置它吗? 编译器在编译时注入对运行时构造函数的调用? 不,二进制文件中有一个名为 .ctors 的部分,其中包含要调用的函数指针列表。该列表由编译器链接器从具有构造函数属性的函数列表中写入,并在静态库的启动代码或动态链接文件中的初始化代码处执行。 模块(.m 文件)构造函数是一个函数,它使用指向编译器生成的模块结构的指针调用运行时,其中包含对其他所有内容的引用。 当然,这样做是为了方便,但是如果您将类描述存储在数据文件中,您可以从文件中构建您需要的结构。不同之处在于编译后的 Objc 生成的结构很容易被运行时使用,因此您将执行 JIT 的那部分工作。

以上是关于Objective-C 运行时如何实例化根元类和其他类描述?的主要内容,如果未能解决你的问题,请参考以下文章

类和元类

iOS底层原理之类,元类,根元类探索(上)

NSBundle 的 -load 方法如何向 Objective-C 运行时注册类和其他运行时资源?

iOS-classobject_getClassobjc_getClassobjc_getMetaClass区别

04 -- 元类和ORM

Objective-C Runtime 文档翻译—序言