这是我参与更文挑战的第5天,活动详情查看: 更文挑战
什么是ISA
指向该对象为实例的类定义的指针,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 {
...
}
Class isa
可以看出isa
就是objc_class *
类型,也就是一个指针,指针类型占用8字节
初始化isa
inline void
objc_object::initIsa(Class cls, bool nonpointer, UNUSED_WITHOUT_INDEXED_ISA_AND_DTOR_BIT bool hasCxxDtor)
{
/* 判断是否是 TaggedPointer
inline bool 内联函数
objc_object::isTaggedPointer()
{
return _objc_isTaggedPointer(this);
}
_objc_isTaggedPointer(const void * _Nullable ptr)
{
// 对象的指正地址 & _OBJC_TAG_MASK == _OBJC_TAG_MASK
// ARM64 / X86_64 _OBJC_TAG_MASK (1UL<<63)
// i386 _OBJC_TAG_MASK 1UL, 最后一位是否为1
return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}
*/
ASSERT(!isTaggedPointer());
// 初始化 一个 isa_t
isa_t newisa(0);
// 是否为nonpointer
if (!nonpointer) {
// 类的isa
newisa.setClass(cls, this);
} else {
// instance 的isa
ASSERT(!DisableNonpointerIsa);
ASSERT(!cls->instancesRequireRawIsa());
// isa_t 赋值
#if SUPPORT_INDEXED_ISA
ASSERT(cls->classArrayIndex() > 0);
newisa.bits = ISA_INDEX_MAGIC_VALUE;
// isa.magic is part of ISA_MAGIC_VALUE
// isa.nonpointer is part of ISA_MAGIC_VALUE
newisa.has_cxx_dtor = hasCxxDtor;
newisa.indexcls = (uintptr_t)cls->classArrayIndex();
#else
newisa.bits = ISA_MAGIC_VALUE;
// isa.magic is part of ISA_MAGIC_VALUE
// isa.nonpointer is part of ISA_MAGIC_VALUE
# if ISA_HAS_CXX_DTOR_BIT
newisa.has_cxx_dtor = hasCxxDtor;
# endif
newisa.setClass(cls, this);
#endif
newisa.extra_rc = 1;
}
// This write must be performed in a single store in some cases
// (for example when realizing a class because other threads
// may simultaneously try to use the class).
// fixme use atomics here to guarantee single-store and to
// guarantee memory order w.r.t. the class index table
// ...but not too atomic because we don't want to hurt instantiation
isa = newisa;
}
对象isa的内存结构
isa_t
是一个联合体,联合体特性是公用一块内存,内部变量的是互斥的,意思是给一个变量赋值,其他变量则没有值
union isa_t {
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
private:
// private.
Class cls;
public:
#if defined(ISA_BITFIELD)
struct {
ISA_BITFIELD; // defined in isa.h
};
bool isDeallocating() {
return extra_rc == 0 && has_sidetable_rc == 0;
}
void setDeallocating() {
extra_rc = 0;
has_sidetable_rc = 0;
}
#endif
void setClass(Class cls, objc_object *obj);
Class getClass(bool authenticated);
Class getDecodedClass(bool authenticated);
};
# if __arm64__
// ARM64 simulators have a larger address space, so use the ARM64e
// scheme even when simulators build for ARM64-not-e.
M1 模拟器
# if __has_feature(ptrauth_calls) || TARGET_OS_SIMULATOR
# define ISA_MASK 0x007ffffffffffff8ULL
# define ISA_MAGIC_MASK 0x0000000000000001ULL
# define ISA_MAGIC_VALUE 0x0000000000000001ULL
# define ISA_HAS_CXX_DTOR_BIT 0
# define ISA_BITFIELD \
uintptr_t nonpointer : 1; \
uintptr_t has_assoc : 1; \
uintptr_t weakly_referenced : 1; \
uintptr_t shiftcls_and_sig : 52; \
uintptr_t has_sidetable_rc : 1; \
uintptr_t extra_rc : 8
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)
# else
// 真机
# define ISA_MASK 0x0000000ffffffff8ULL 掩码 取shiftcls 存的是类
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
# define ISA_HAS_CXX_DTOR_BIT 1
# define ISA_BITFIELD \
uintptr_t nonpointer : 1; // 表示是否对 isa 指针开启指针优化
0:纯isa指针,
1:不⽌是类对象地址, isa 中包含了类
信息、对象的引⽤计数等
\
uintptr_t has_assoc : 1; // 关联对象标志位,0没有,1存在 \
uintptr_t has_cxx_dtor : 1; // 该对象是否有 C++ 或者 Objc 的析构器, 如果有析构函数,则需要做析构逻辑,
如果没有,则可以更快的释放对象 \
uintptr_t shiftcls : 33; // 存储类指针的值。开启指针优化的情况下
在 arm64 架构中有 33 位⽤来存储类指针
uintptr_t magic : 6; // 用于调试器判断当前是真的对象还是未初始化的空间 \
uintptr_t weakly_referenced : 1; // 是否是弱引用, \
uintptr_t unused : 1; // 是否使用过 \
uintptr_t has_sidetable_rc : 1; // 当引用计数大于10,存储进位 \
uintptr_t extra_rc : 19 // 存储对象的引用计数,实则为 引用计数-1, 大于10,存到 has_sidetable_rc 中
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
# endif
可以看出对象的isa
[4~37]存的是class
通过lldb探索isa
创建一个对象打上断点
对象的isa
- 根据上面的打印可以看出,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
是同级的,都是根类
苹果官方
总结
- 万物皆对象,类只有一块地址,相当于系统帮你创建了一个单例对象,然后我们基于类这个对象继承再开辟的新的内存创建对象
元类
也有继承关系,元类
继承父类的元类
根元类
继承根类
,根类继承nil