1.OC中所有的对象都有一个isa指针,这个指针在arm64优化后,使用共生体存储着是否有weak引用信息,销毁的时候会先检查该类是否有weak引用。
2.OC的对象引用计数都存储在SideTable里,SideTables是一个64个元素长度8个元素长度的hash数组,里面存储了SideTable。
SideTables的hash键值就是一个对象obj的地址。一个obj,对应了一个SideTable。但是一个SideTable,会对应多个obj。因为SideTable的数量只有64个,所以会有很多obj共用同一个SideTable。
struct SideTable {
spinlock_t slock; // 自旋锁
RefcountMap refcnts; // 强引用哈希表
weak_table_t weak_table; // 弱引用表
};
/**
全局hash表,以对象指针地址为key,entries里面存储着当前对象的所有弱引用指针
*/
struct weak_table_t {
weak_entry_t *weak_entries; // 保存了对象的所有weak指针
size_t num_entries; // weak对象的存储空间
uintptr_t mask; // 参与判断引用计数辅助量
uintptr_t max_hash_displacement;// 最大偏移量
};
struct weak_entry_t {
DisguisedPtr<objc_object> referent;
union {
struct {
weak_referrer_t *referrers;
uintptr_t out_of_line_ness : 2;
uintptr_t num_refs : PTR_MINUS_2;
uintptr_t mask;
uintptr_t max_hash_displacement;
};
struct {
// out_of_line_ness field is low bits of inline_referrers[1]
weak_referrer_t inline_referrers[WEAK_INLINE_COUNT];
};
};
};
-
weak引用是通过runtime来支持的,runtime会调用方法objc_initweak,这个方法接受两个参数,一个引用对象的指针地址,用于在最后将weak指针指向对象置为nil。
-
objc_initweak实质上调用了storeWeak方法,storeWeak() 的作用是更新指针指向,创建对应的弱引用表。
__weak id weakObj = obj;
// 本质上会调用objc_initWeak函数
id
objc_initWeak(id *location, id newObj)
{
// 1.判断newObj是否为nil,如果是nil则将当前的指针置为nil
if (!newObj) {
*location = nil;
return nil;
}
// 2. 如果传入的指针不为nil,则会调用storeWeak。
// storeWeak() 的作用是更新指针指向,创建对应的弱引用表。
return storeWeak<DontHaveOld, DoHaveNew, DoCrashIfDeallocating>
(location, (objc_object*)newObj);
}
- weak对象释放时,底层会调用_objc_rootDealloc的rootDealloc方法,查看isa中的是否有若引用,没有会直接释放。如果有则会调用object_dispose()方法,然后做清除成员变量、移除关联对象操作,把key从weaktable中移除,最后将当前对象的弱指针置为nil。
// 1. 会先调用_objc_rootDealloc
void
_objc_rootDealloc(id obj)
{
assert(obj);
obj->rootDealloc();
}
// 2. 看是否能直接释放
inline void
objc_object::rootDealloc()
{
if (isTaggedPointer()) return; // fixme necessary?
if (fastpath(isa.nonpointer && // 如果是nonpointer(优化过的isa指针)
!isa.weakly_referenced && // 没有弱引用
!isa.has_assoc && // 没有关联对象
!isa.has_cxx_dtor && // 没有c++析构函数
!isa.has_sidetable_rc)) // 没有使用sidetable存储引用计数
{
assert(!sidetable_present());
free(this); // 直接释放对象
}
else {
object_dispose((id)this);
}
}
// 3. 如果不能直接释放则调用
id
object_dispose(id obj)
{
if (!obj) return nil;
objc_destructInstance(obj);
free(obj);
return nil;
}
// 4. c++和关联对象释放以及成功变量擦除
void *objc_destructInstance(id obj)
{
if (obj) {
// Read all of the flags at once for performance.
bool cxx = obj->hasCxxDtor();
bool assoc = obj->hasAssociatedObjects();
// This order is important.
if (cxx) object_cxxDestruct(obj); // 清除成员变量
if (assoc) _object_remove_assocations(obj); // 移除关联对象
obj->clearDeallocating(); // 将指向当前对象的弱指针置为nil
}
return obj;
}
inline void
objc_object::clearDeallocating()
{
if (slowpath(!isa.nonpointer)) {
// Slow path for raw pointer isa.
sidetable_clearDeallocating();
}
else if (slowpath(isa.weakly_referenced || isa.has_sidetable_rc)) {
// Slow path for non-pointer isa with weak refs and/or side table data.
clearDeallocating_slow();
}
assert(!sidetable_present());
}