底层原理:class和meta-class的结构
2022-02-28 本文已影响0人
飘摇的水草
- class和meta-class对象的类型都是 struct objc_class 结构体
struct objc_class 结构分析
- 在源码中的部分代码如下:源码版本:objc4-
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 *data() const {
return bits.data();
}
...
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
- 从上面可以看出 struct objc_class 的内存结构可以理解为:
struct objc_class {
Class isa;
Class superclass;
cache_t cache; // 方法缓存
class_data_bits_t bits; // 用于获取具体的类信息
};
- 通过bits获取类信息
class_rw_t *data() const {
return bits.data();
}
- 通过上面这个方法,可以得到一个可读写信息表:
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint16_t witness;
#if SUPPORT_INDEXED_ISA
uint16_t index;
#endif
explicit_atomic<uintptr_t> ro_or_rw_ext;
Class firstSubclass;
Class nextSiblingClass;
// 获取只读信息表
const class_ro_t *ro() const {
auto v = get_ro_or_rwe();
if (slowpath(v.is<class_rw_ext_t *>())) {
return v.get<class_rw_ext_t *>()->ro;
}
return v.get<const class_ro_t *>();
}
// 获取方法列表
const method_array_t methods() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->methods;
} else {
return method_array_t{v.get<const class_ro_t *>()->baseMethods()};
}
}
// 获取属性列表
const property_array_t properties() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->properties;
} else {
return property_array_t{v.get<const class_ro_t *>()->baseProperties};
}
}
// 获取协议列表
const protocol_array_t protocols() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->protocols;
} else {
return protocol_array_t{v.get<const class_ro_t *>()->baseProtocols};
}
}
- class_ro_t 只读信息表部分源码如下:
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize; // instance对象占用的内存空间
#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和superclass答疑
- 类对象和原类对象是什么时候分配内存?什么时候释放的?
答:类对象和原类对象是一直在内存中,直到程序退出才销毁,类不管用不用都会被载进在内存,只要程序一启动,执行完main函数,就加载这些类信息。
如果用到这个类,就会调用这个类的load方法,如果不用,则不会调用Load方法,实例对象里存放的成员变量指的是成员变量的值,而类对象里放的是成员变量的信息,如类型和名称等。