isa分析到元类
- 我们知道
Class
是objc_class*
类型也就是一个指针,objc_class
是继承与objc_object
, 所以Class
也是有isa
的
typedef struct objc_class *Class;
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
struct objc_class: objc_object {
// isa
...
}
Class isa
复制代码
lldb分析isa
- 通过对象的
isa
可以得到类,那类的isa
又存的是什么呢,还以可以通过lldb
打印来查看结果
- 根据上面的打印可以看出,isa(–>) 对象–>类–>元类–>根元类–>根元类
- 类的
isa
存到的就是元类
,不需要通过mask
掩码去得到,只有对象的才是nonpointer
。因为只有对象才有引用计数,弱引用等 - 也可以得出其实类也是一个是对象,这也应证万物接对象
teacher
是继承person
, 通过lldb查看一下tacher
的isa
- 可以得出
teacher
的元类
也是指向根元类
继承关系的isa
->
表示继承
meta
表示元类
WLWTeacher -> WLWPerson -> NSObject -> nil
WLWTeacher(meta) -> WLWPerson(meta) -> NSObject(meta) -> NSobject -> nil
元类
也是有继承
的关系的,会继承父类的元类,一直到根元类- 根元类的继承根类
NSProxy 的isa与继承
NSProxy
是遵守NSObject
协议的,也是根类,所以他跟NSOject根类一样,只是根类换成的NSProxy
- 所以
NSProxy
与NSObjec
是同级的,都是根类
代码打印
// NSObject实例对象
NSObject *object1 = [NSObject alloc];
// NSObject类
Class class = object_getClass(object1);
// NSObject元类
Class metaClass = object_getClass(class);
// NSObject根元类
Class rootMetaClass = object_getClass(metaClass);
// NSObject根根元类
Class rootRootMetaClass = object_getClass(rootMetaClass);
NSLog(@"\n%p 实例对象\n%p 类\n%p 元类\n%p 根元类\n%p 根根元类",object1,class,metaClass,rootMetaClass,rootRootMetaClass);
// LGPerson元类
Class pMetaClass = object_getClass(LGPerson.class);
Class psuperClass = class_getSuperclass(pMetaClass);
NSLog(@"%@ - %p",psuperClass,psuperClass);
// LGTeacher -> LGPerson -> NSObject
// 元类也有一条继承链
Class tMetaClass = object_getClass(LGTeacher.class);
Class tsuperClass = class_getSuperclass(tMetaClass);
NSLog(@"%@ - %p",tsuperClass,tsuperClass);
// NSObject 根类特殊情况
Class nsuperClass = class_getSuperclass(NSObject.class);
NSLog(@"%@ - %p",nsuperClass,nsuperClass);
// 根元类 -> NSObject
Class rnsuperClass = class_getSuperclass(metaClass);
NSLog(@"%@ - %p",rnsuperClass,rnsuperClass);
复制代码
苹果官方
总结
- 万物皆对象,类只有一块地址,相当于系统帮你创建了一个单例对象,然后我们基于类这个对象继承再开辟的新的内存创建对象
元类
也有继承关系,元类
继承父类的元类
根元类
继承根类
,根类继承nil
- 对象 isa -> 类 isa -> 元类 isa -> 根元类 isa -> 根元类
- 根类 isa -> 根元类 isa
源码分析类的结构
struct objc_class : objc_object {
objc_class(const objc_class&) = delete;
objc_class(objc_class&&) = delete;
void operator=(const objc_class&) = delete;
void operator=(objc_class&&) = delete;
// 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
.....
.....
}
复制代码
- 由于类的结构里有很多的方法,我们先分析 类结构里的成员变量
- 类里有4个成员变量,
Class ISA
- 第一个是隐藏的
Class ISA
,继承自objc_object
, 我们也知道其指向元类
, 是一个指针,所以是8字节
superClass
- 第二个
superClass
很明显是指向父类, 也是个指针8字节
cache_t cache
- 第三个
cache_t cache
,这个非常的重要,很好理解是缓存,具体缓存了什么,还需要进一步探索- 查看一下
cache_t
结构体
struct cache_t { private: // buckets 的指针/首地址 , explicit_atomic<T> 确定类型 允许转换, uintptr_t = unsigned long 无符号长整型 explicit_atomic<uintptr_t> _bucketsAndMaybeMask; // 8字节 // 联合体,内存共享,成员变量互斥 union { struct { // mask_t: mac: uint32_t // 掩码 explicit_atomic<mask_t> _maybeMask; //4字节 #if __LP64__ // 标记 uint16_t _flags; //2字节 #endif //已占用数量 uint16_t _occupied; //2字节 }; // 指针,原始的规则缓存 explicit_atomic<preopt_cache_t *> _originalPreoptCache; // 8字节 }; 复制代码
- 可以算出
cache_t
大小是16
字节
- 查看一下
class_data_bits_t
- 第四个
class_data_bits_t bits
,里放了些数据根据注释可以看出是class_rw_t *
加上rr/alloc
的自定义flags
,源码也可与看粗 其占用8字节
struct class_data_bits_t {
// friend 友元
friend objc_class;
// Values are the FAST_ flags above.
uintptr_t bits; // 8字节
。。。。。
。。。。。
复制代码
lldb分析类的结构
- 根据
cache_t
的内部结构可以得出0x000000019a7033e0
是_bucketsAndMaybeMask
,0x0000801900000000
是那个联合体 class_data_bits_t
就是其内部的bits
类的bits数据分析
- 我们知道如何找到
bits
, 我们在源码环境中将其打印出来 - 在非源码环境没有
class_data_bits_t
类型,无法打印其结构,但我们可以通过仿写底层代码来实现打印
class_rw_t *data() const {
return bits.data();
}
复制代码
- 通过
lldb
打印出内存地址,再通过objc_class
里提供的方法我们拿到$46 = class_rw_t
firstSubClass
是运行时,赋值的- 可以看出类是个树状结构
class_rw_t (dirty memory)
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; // 兄弟类
复制代码
class_rw_t 的 falgs 标记
// Values for class_rw_t->flags
// These are not emitted by the compiler and are never used in class_ro_t.
// Their presence should be considered in future ABI versions.
// class_t->data is class_rw_t, not class_ro_t
#define RW_REALIZED (1<<31)
// class is unresolved future class
#define RW_FUTURE (1<<30)
// class is initialized
#define RW_INITIALIZED (1<<29)
// class is initializing
#define RW_INITIALIZING (1<<28)
// class_rw_t->ro is heap copy of class_ro_t
#define RW_COPIED_RO (1<<27)
// class allocated but not yet registered
#define RW_CONSTRUCTING (1<<26)
// class allocated and registered
#define RW_CONSTRUCTED (1<<25)
// available for use; was RW_FINALIZE_ON_MAIN_THREAD
// #define RW_24 (1<<24)
// class +load has been called
#define RW_LOADED (1<<23)
#if !SUPPORT_NONPOINTER_ISA
// class instances may have associative references
#define RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS (1<<22)
#endif
// class has instance-specific GC layout
#define RW_HAS_INSTANCE_SPECIFIC_LAYOUT (1 << 21)
// class does not allow associated objects on its instances
#define RW_FORBIDS_ASSOCIATED_OBJECTS (1<<20)
// class has started realizing but not yet completed it
#define RW_REALIZING (1<<19)
#if CONFIG_USE_PREOPT_CACHES
// this class and its descendants can't have preopt caches with inlined sels
#define RW_NOPREOPT_SELS (1<<2)
// this class and its descendants can't have preopt caches
#define RW_NOPREOPT_CACHE (1<<1)
#endif
// class is a metaclass (copied from ro)
#define RW_META RO_META // (1<<0)
复制代码
class_rw_t
的内部一些方法
// 获取ro clean memory
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_or_rw_ext)->ro;
}
return v.get<const class_ro_t *>(&ro_or_rw_ext);
}
// 设置ro clean memory
void set_ro(const class_ro_t *ro) {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
v.get<class_rw_ext_t *>(&ro_or_rw_ext)->ro = ro;
} else {
set_ro_or_rwe(ro);
}
}
// 获取方法
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 *>(&ro_or_rw_ext)->methods;
} else {
return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->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 *>(&ro_or_rw_ext)->properties;
} else {
return property_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->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 *>(&ro_or_rw_ext)->protocols;
} else {
return protocol_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProtocols};
}
}
复制代码
properties()
- 成员变量不会存在这里,只有属性
property
methods()
- 方法里有属性生成的
set, get
方法 - 没有
类方法
,也就是所谓的+
号方法,存有-
号方法 types = 0x0000000100003df7 "v24@0:8@16"
, 第一个v
表示返回值void
, 下边是对照表
protocols()
protocols
底层是protocol_t
结构体
class_ro_t
ivars
- 成员变量存在了
class_ro_t
的ivars
里, - 并且里面也存储了属性生成的带有下划线
_
的变量
baseProperties
- ro
baseProperties
里的值与 rwpropertires
一样
baseMethodList
ro
rw
- 可以看出这连个地址是一样的, 所里存的方法是一样的
baseProtocols
rw
ro
- 地址也是一样的
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END