当对象开始释放的时候,会调用dealloc方法
- (void)dealloc {
_objc_rootDealloc(self);
}
void _objc_rootDealloc(id obj)
{
ASSERT(obj);
obj->rootDealloc();
}
inline void objc_object::rootDealloc()
{
if (isTaggedPointer()) return; // fixme necessary?
if (fastpath(isa.nonpointer &&
!isa.weakly_referenced &&
!isa.has_assoc &&
!isa.has_cxx_dtor &&
!isa.has_sidetable_rc))
{
assert(!sidetable_present());
free(this);
}
else {
object_dispose((id)this);
}
}
id object_dispose(id obj)
{
if (!obj) return nil;
objc_destructInstance(obj);
free(obj);
return nil;
}
上面的方法和函数,都是判断后调用下一个函数,从objc_destructInstance
开始进入释放流程
void *objc_destructInstance(id obj)
{
if (obj) {
// 判断是否有c++析构函数和关联对象
bool cxx = obj->hasCxxDtor();
bool assoc = obj->hasAssociatedObjects();
// 调用析构函数和移除关联对象
if (cxx) object_cxxDestruct(obj); //释放成员变量
if (assoc) _object_remove_assocations(obj);// 移除关联对象
obj->clearDeallocating();// 清理相关引用
}
return obj;
}
clearDeallocating
inline void
objc_object::clearDeallocating()
{
// 是否优化了iOS存储
if (slowpath(!isa.nonpointer)) {
//没有采用优化isa引用计数 清理obj存储在sideTable中的引用计数等信息
sidetable_clearDeallocating();
}
// 启用了isa优化,则判断是否使用了sideTable
// 通过是否做了weak引用(isa.weakly_referenced ) 或 是否使用了sideTable的辅助引用计数(isa.has_sidetable_rc)
else if (slowpath(isa.weakly_referenced || isa.has_sidetable_rc)) {
//释放weak 和引用计数
clearDeallocating_slow();
}
assert(!sidetable_present());
}
clearDeallocating_slow
NEVER_INLINE void objc_object::clearDeallocating_slow()
{
ASSERT(isa.nonpointer && (isa.weakly_referenced || isa.has_sidetable_rc));
// 在全局的SideTables中,以this指针为key,找到对应的SideTable
SideTable& table = SideTables()[this];
table.lock();
if (isa.weakly_referenced) {
// 在SideTable的weak_table中对this进行清理工作
weak_clear_no_lock(&table.weak_table, (id)this);
}
// 如果采用了SideTable做引用计数
if (isa.has_sidetable_rc) {
//在SideTable的引用计数中移除this
table.refcnts.erase(this);
}
table.unlock();
}
部分SideTable的信息可以查看 https://www.jianshu.com/p/42b05f37710d
table.refcnts.erase(this);
table.refcnts 指的是 SideTable结构体的变量
struct SideTable {
spinlock_t slock;// 防止资源竞争的锁
RefcountMap refcnts; // 协助对象的 isa 指针的 extra_rc 共同引用计数的变量
weak_table_t weak_table; // weak 全局 hash 表
}
// RefcountMap 是一个模板类
// key : DisguisedPtr<objc_object>类型
// value : size_t类型
// RefcountMapValuePurgeable, 内部会回调 isPurgeable 方法,判断是否需要自动清除
typedef objc::DenseMap<DisguisedPtr<objc_object>,size_t,RefcountMapValuePurgeable> RefcountMap;
struct RefcountMapValuePurgeable {
static inline bool isPurgeable(size_t x) {
return x == 0;
}
};
DenseMap是llvm库中的类,是一个简单的二次探测哈希表,擅长支持小的键和值。RefcountMap是一个hash map,其key是obj的DisguisedPtr<objc_object>,而value,则是obj对象的引用计数,同时,这个map还有个加强版功能,当引用计数为0时,会自动将对象数据清除。
weak_clear_no_lock
//清理weak_table,同时将所有weak引用该对象的ptr置为nil
void weak_clear_no_lock(weak_table_t *weak_table, id referent_id)
{
objc_object *referent = (objc_object *)referent_id;
// 找到referent在weak_table中对应的weak_entry_t
weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);
if (entry == nil) {
/// XXX shouldn't happen, but does with mismatched CF/objc
//printf("XXX no entry for clear deallocating %p\n", referent);
return;
}
// zero out references
weak_referrer_t *referrers;
size_t count;
// 找出weak引用referent的weak 指针地址数组以及数组长度
// 是否使用动态数组
if (entry->out_of_line()) {
referrers = entry->referrers;
count = TABLE_SIZE(entry);
}
else {
referrers = entry->inline_referrers;
count = WEAK_INLINE_COUNT;
}
// 遍历所有的所引用weak指针
for (size_t i = 0; i < count; ++i) {
// 取出每个weak ptr的地址
objc_object **referrer = referrers[i];
if (referrer) {
// 如果weak ptr确实weak引用了referent,则将weak ptr设置为nil,这也就是为什么weak 指针会自动设置为nil的原因
if (*referrer == referent) {
*referrer = nil;
}
else if (*referrer) {
// 如果所存储的weak ptr没有weak 引用referent,这可能是由于runtime代码的逻辑错误引起的,报错
_objc_inform("__weak variable at %p holds %p instead of %p. "
"This is probably incorrect use of "
"objc_storeWeak() and objc_loadWeak(). "
"Break on objc_weak_error to debug.\n",
referrer, (void*)*referrer, (void*)referent);
objc_weak_error();
}
}
}
// 由于referent要被释放了,因此referent的weak_entry_t也要移除出weak_table
weak_entry_remove(weak_table, entry);
}
object_cxxDestruct
void object_cxxDestruct(id obj)
{
if (!obj) return;
if (obj->isTaggedPointer()) return;
object_cxxDestructFromClass(obj, obj->ISA());
}
static void object_cxxDestructFromClass(id obj, Class cls)
{
void (*dtor)(id);
for ( ; cls; cls = cls->superclass) {
// 如果类没有析构函数了,就返回
if (!cls->hasCxxDtor()) return;
// 找到析构函数
dtor = (void(*)(id))
lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct);
if (dtor != (void(*)(id))_objc_msgForward_impcache) { // 如果不进行消息转发
if (PrintCxxCtors) {
_objc_inform("CXX: calling C++ destructors for class %s",
cls->nameForLogging());
}
// 执行析构函数
(*dtor)(obj);
}
}
}
SEL_cxx_destruct = sel_registerNameNoLock(".cxx_destruct", NO);
最终是 .cxx_destruct 方法被调用了。
.cxx_destruct
.cxx_destruct 函数是在编译的时候由前端编译器(clang)自动插入的。
实现原理是遍历所有实例变量,调用 objc_storeStrong 函数
void objc_storeStrong(id *location, id obj)
{
id prev = *location;
if (obj == prev) {
return;
}
objc_retain(obj);
*location = obj;
objc_release(prev);
}
// 只要执行 objc_storeStrong(&ivar, null) 就能释放ivar实例变量。
网友评论