iOS runtime 内存模型
源码下载地址:https://opensource.apple.com/tarballs/objc4/,我下载了当前最新的objc4-779.1.tar.gz
注:iPhone 程序和 Mac OS X v10.5 及以后的系统中的 64 位程序使用的都是 Objective-C 运行时系统的objc 2.0版本。源码中有大量宏条件, 注意查看条件。如
#if !__OBJC2__
, 此条件下的代码是无效的,网上流传的许多以前的资料是过时的,有助于理解,但注意区分。
对象
OC是一门面向对象的语言,一切皆对象。OC中定义的对象是struct objc_object
,被定义在了objc-private.h
文件中。
struct objc_object {
private:
isa_t isa;
public:
Class ISA();
Class rawISA();
Class getIsa();
uintptr_t isaBits() const;
void initIsa(Class cls /*nonpointer=false*/);
void initClassIsa(Class cls /*nonpointer=maybe*/);
void initProtocolIsa(Class cls /*nonpointer=maybe*/);
void initInstanceIsa(Class cls, bool hasCxxDtor);
Class changeIsa(Class newCls);
....
}
这里面有一个最重要的私有变量isa
,它是一个指针,指向的是什么,用一个清晰明了的图来看一下(superclass
看下段中类的源码就明白了)。
yy大神画的这个图我觉得更清晰明了,本来自己想画的就是这种
注:根元类一般是
NSObject
, 还有一个NSProxy
,这里假定Cat
继承自NSObject
,如果继承自NSProxy
,图中的NSObject
换成NSProxy
即可。
此文件中也能找到id
的定义,typedef struct objc_object *id;
。那么也就能理解为什么id
能指向任何对象了。
类
类其实也是一个对象,被定义为struct objc_class
,在objc-runtime-new.h
文件中,继承自objc_object
。
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() const {
return bits.data();
}
void setData(class_rw_t *newData) {
bits.setData(newData);
}
void setInfo(uint32_t set) {
ASSERT(isFuture() || isRealized());
data()->setFlags(set);
}
....
}
cache_t cache
cache 是为了方法调用性能优化,将调用过的方法缓存,当对某个对象发送消息时先从cache中找,找不到再到isa指向的类中寻找方法实现。提高效率。
class_data_bits_t
内容很少,重点在包装的bits.data()
.
class_rw_t
是bits.data()
返回的类型。class_rw_t
可以动态修改。可以动态添加方法、属性到methods
,properties
,properties
中。class_rw_t
包含class_ro_t
。
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint16_t version;
uint16_t witness;
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
...
class_ro_t
存储的大多是类在编译时就已经确定的信息。
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
const char * name;
method_list_t * baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
...
}
元类
类也是对象,是某个类的实例。这个“某个类”被称为元类。
- 类的isa指针指向其元类
- 元类也是某个类的实例,这个“某个类”被称为根元类。
- 元类的isa指针指向根元类,根元类的isa指针指向自己
- 类方法保存在元类中
参考:
- 证明isa指向关系,以及簇类
https://blog.csdn.net/u013480070/article/details/100155929 - 对象的方法存在类中,类方法存在元类中
https://juejin.im/post/5ac649b6518825558a06da89 - 雷纯锋Objective-C 对象模型
- YY大神的 Objective-C 中的类和对象
- 玉令天下Objective-C Runtime