简介
- 这篇文章主要介绍的内容包括根据源码来理解对象从“出生”到“消亡”的整个生命周期。
对象的出生
-
alloc 方法做了什么?
// 由源码可知 + (id)alloc { return _objc_rootAlloc(self); } // 接着👇 id _objc_rootAlloc(Class cls) { return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/); } // 接着👇 static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, bool allocWithZone=false) { if (checkNil && !cls) return nil; #if __OBJC2__ // 首先判断当前类是否 hasCustomAWZ ,该方法定义如下 /** bool hasCustomAWZ() { return ! bits.hasDefaultAWZ(); } bool hasDefaultAWZ() { return data()->flags & RW_HAS_DEFAULT_AWZ; } 而 RW_HAS_DEFAULT_AWZ 的定义如下:表示是否拥有默认创建方法 // class or superclass has default alloc/allocWithZone: implementation // Note this is is stored in the metaclass. #define RW_HAS_DEFAULT_AWZ (1<<16) */ // 无默认创建方法 if (! cls->ISA()->hasCustomAWZ()) { // No alloc/allocWithZone implementation. Go straight to the allocator. // fixme store hasCustomAWZ in the non-meta class and // add it to canAllocFast's summary if (cls->canAllocFast()) { // No ctors, raw isa, etc. Go straight to the metal. // 判断是否有析构函数 bool dtor = cls->hasCxxDtor(); // 直接初始化,并且置为 0 id obj = (id)calloc(1, cls->bits.fastInstanceSize()); // 创建失败,则被 badHandler 捕获 if (!obj) return callBadAllocHandler(cls); // 然后初始化 obj->initInstanceIsa(cls, dtor); return obj; } else { // Has ctor or raw isa or something. Use the slower path. /** // 如果无法进行快速创建,则直接在 zone 中分配一块空间来创建 id class_createInstance(Class cls, size_t extraBytes) { return _class_createInstanceFromZone(cls, extraBytes, nil); } */ id obj = class_createInstance(cls, 0); if (!obj) return callBadAllocHandler(cls); return obj; } } #endif // No shortcuts available. if (allocWithZone) return [cls allocWithZone:nil]; return [cls alloc]; }
-
最终都调用了
_class_createInstanceFromZone方法// 现在我们来看一下这个方法 static __attribute__((always_inline)) id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, bool cxxConstruct = true, size_t *outAllocatedSize = nil) { if (!cls) return nil; assert(cls->isRealized()); // Read class's info bits all at once for performance // 判断是否有析构函数 bool hasCxxCtor = cls->hasCxxCtor(); bool hasCxxDtor = cls->hasCxxDtor(); // 判断是否能够快速初始化 bool fast = cls->canAllocNonpointer(); // 计算当前实例的大小 size_t size = cls->instanceSize(extraBytes); if (outAllocatedSize) *outAllocatedSize = size; id obj; if (!zone && fast) { // 如果 zone 为空 并且可以快速构造,则直接使用 calloc 函数快速构造一个 size 大小的位置 obj = (id)calloc(1, size); if (!obj) return nil; // 初始化数据 obj->initInstanceIsa(cls, hasCxxDtor); } else { // 如果不支持快速构造并且有 zone,则直接在 zone 上分配一个 size 大小的存储空间 if (zone) { obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size); // 如果不支持快速构造并且无 zone,则直接使用 calloc 分配一个 size 大小的存储空间 } else { obj = (id)calloc(1, size); } if (!obj) return nil; // Use raw pointer isa on the assumption that they might be // doing something weird with the zone or RR. obj->initIsa(cls); } if (cxxConstruct && hasCxxCtor) { obj = _objc_constructOrFree(obj, cls); } return obj; } -
而我们之后,需要调用 init 方法,来实现对象真正的完成出生过程
- (id)init { return _objc_rootInit(self); } _objc_rootInit(id obj) { // In practice, it will be hard to rely on this function. // Many classes do not properly chain -init calls. return obj; }至此,对象的出生真正完成
对象的生长
-
首先定义如下类
#import <Foundation/Foundation.h> @interface LYObject : NSObject @property (nonatomic, strong) NSString *name; - (void)study; + (void)sleep; @end @implementation LYObject - (void)study { NSLog(@"studying"); } + (void)sleep { NSLog(@"sleeping"); } @end -
然后在 viewController 中调用它
- (void)testSuperClass { LYObject *obj = [[LYObject alloc] init]; NSLog(@"class - %@", [obj class]); NSLog(@"superClass - %@", [obj superclass]); NSLog(@"metaClass -- %@", object_getClass([obj class])); NSLog(@"metaClass's metaClass -- %@", object_getClass(object_getClass([obj class]))); NSLog(@"metaClass's superClass -- %@", [object_getClass([obj class]) superclass]); // 打印结果 /** 2017-12-28 21:16:43.972104+0800 RuntimeTest[60981:11200702] class - LYObject 2017-12-28 21:16:43.972300+0800 RuntimeTest[60981:11200702] superClass - NSObject 2017-12-28 21:16:43.972417+0800 RuntimeTest[60981:11200702] metaClass -- LYObject 2017-12-28 21:16:43.972530+0800 RuntimeTest[60981:11200702] metaClass's metaClass -- NSObject 2017-12-28 21:16:43.972626+0800 RuntimeTest[60981:11200702] metaClass's superClass -- NSObject */ } - (void)testPoiter { Class currentClass = [LYObject class]; for (int i = 1; i < 5; i++) { NSLog(@"Following the isa pointer %d times gives %p %@", i, currentClass,currentClass); currentClass = object_getClass(currentClass); } NSLog(@"NSObject's class is %p", [NSObject class]); NSLog(@"NSObject's meta class is %p", object_getClass([NSObject class])); NSLog(@"NSObject's meta class's meta class is %p", object_getClass(object_getClass([NSObject class]))); /** 2017-12-28 21:18:58.430792+0800 RuntimeTest[61004:11204340] Following the isa pointer 1 times gives 0x1036f3060 LYObject // 表明此时指向 LYObject 的类 2017-12-28 21:18:58.430971+0800 RuntimeTest[61004:11204340] Following the isa pointer 2 times gives 0x1036f3038 LYObject // 此时指向 LYObject 的 meta class 2017-12-28 21:18:58.431090+0800 RuntimeTest[61004:11204340] Following the isa pointer 3 times gives 0x1046aae58 NSObject // 此时指向 LYObject 的 meta class 的 superClass 2017-12-28 21:18:58.431185+0800 RuntimeTest[61004:11204340] Following the isa pointer 4 times gives 0x1046aae58 NSObject // 表面实际上 NSObject 类的 meta class 指针指向自己 2017-12-28 21:18:58.431277+0800 RuntimeTest[61004:11204340] NSObject's class is 0x1046aaea8 2017-12-28 21:18:58.431501+0800 RuntimeTest[61004:11204340] NSObject's meta class is 0x1046aae58 2017-12-28 21:18:58.431793+0800 RuntimeTest[61004:11204340] NSObject's meta class's meta class is 0x1046aae58 */ } -
由这两个方法可以看出,实际上 LYObject 对象的 class 为 LYObject, LYObject 类的 class(即metaClass)为 LYObject, 但是 LYObject 的 metaClass 的 superClass 为 NSObject,如图

-
我们进一步可以看到,在黑框中的两个 class 实际上是一对 classPair,在 Runtime 的代码定义中如下:
/** @param superclass 表示这个方法首先指明新建 class 的 superclass,如果新建的 class 是一个 rootclass,则直接传递 nil @param name 表示新创建的 class 的 name, 这个 name 的修饰符为 copy @param extraBytes 表示 The number of bytes to allocate for indexed ivars at the end of the class and metaclass objects. This should usually be \c 0. 通常为 0 创建一对新的 class pair 的步骤, 首先,调用 objc_allocateClassPair 方法 然后,调用 class_addMethod or class_addIvars 来给当前的类添加编译时的属性 然后,调用 objc_registerClassPair 来注册这个 class ,此时这个新的 class 就准备好了! 最后,在 Runtime 时期,动态的为类添加 实例变量和 实例方法,而类方法应该被添加到 metaclass 中 */ Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes) { Class cls, meta; rwlock_writer_t lock(runtimeLock); // Fail if the class name is in use. // Fail if the superclass isn't kosher. if (getClass(name) || !verifySuperclass(superclass, true/*rootOK*/)) { return nil; } // Allocate new classes. cls = alloc_class_for_subclass(superclass, extraBytes); meta = alloc_class_for_subclass(superclass, extraBytes); // fixme mangle the name if it looks swift-y? objc_initializeClassPair_internal(superclass, name, cls, meta); return cls; } // 在上述方法中给 cls 和 meta 指针赋值时, 调用了 alloc_class_for_subclass 方法,这个方法实际上就是创建了一个类的地址空间给它使用。 static Class alloc_class_for_subclass(Class supercls, size_t extraBytes) { if (!supercls || !supercls->isSwift()) { return _calloc_class(sizeof(objc_class) + extraBytes); } } // 也调用了另一个方法 objc_initializeClassPair_internal, 在这个方法中👇 // &UnsetLayout is the default ivar layout during class construction static const uint8_t UnsetLayout = 0; static void objc_initializeClassPair_internal(Class superclass, const char *name, Class cls, Class meta) { runtimeLock.assertWriting(); // 首先声明两个储存类信息的指针 class_ro_t *cls_ro_w, *meta_ro_w; // 为 class_rw_t 结构体创建控件,然后初始化为 0 cls->setData((class_rw_t *)calloc(sizeof(class_rw_t), 1)); meta->setData((class_rw_t *)calloc(sizeof(class_rw_t), 1)); cls_ro_w = (class_ro_t *)calloc(sizeof(class_ro_t), 1); meta_ro_w = (class_ro_t *)calloc(sizeof(class_ro_t), 1); // 然后使 data() 返回的 class_rw_t 指针的 ro 变量指向刚刚声明的两个指针 cls_ro_w 和 meta_ro_w cls->data()->ro = cls_ro_w; meta->data()->ro = meta_ro_w; // 接着设置初始化信息 /** // class allocated but not yet registered #define RW_CONSTRUCTING (1<<26) // class_rw_t->ro is heap copy of class_ro_t #define RW_COPIED_RO (1<<27) // 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) // available for use // #define RW_20 (1<<20) // class has started realizing but not yet completed it #define RW_REALIZING (1<<19) */ cls->data()->flags = RW_CONSTRUCTING | RW_COPIED_RO | RW_REALIZED | RW_REALIZING; meta->data()->flags = RW_CONSTRUCTING | RW_COPIED_RO | RW_REALIZED | RW_REALIZING; // 设置 version, 7 表示 meta class cls->data()->version = 0; meta->data()->version = 7; // 设置 flag RO_META 表示 meta class cls_ro_w->flags = 0; meta_ro_w->flags = RO_META; // 如果都没有 superclass, 则为 rootclass if (!superclass) { cls_ro_w->flags |= RO_ROOT; meta_ro_w->flags |= RO_ROOT; } if (superclass) { cls_ro_w->instanceStart = superclass->unalignedInstanceSize(); meta_ro_w->instanceStart = superclass->ISA()->unalignedInstanceSize(); cls->setInstanceSize(cls_ro_w->instanceStart); meta->setInstanceSize(meta_ro_w->instanceStart); } else { cls_ro_w->instanceStart = 0; meta_ro_w->instanceStart = (uint32_t)sizeof(objc_class); cls->setInstanceSize((uint32_t)sizeof(id)); // just an isa meta->setInstanceSize(meta_ro_w->instanceStart); } cls_ro_w->name = strdupIfMutable(name); meta_ro_w->name = strdupIfMutable(name); cls_ro_w->ivarLayout = &UnsetLayout; cls_ro_w->weakIvarLayout = &UnsetLayout; meta->chooseClassArrayIndex(); cls->chooseClassArrayIndex(); // Connect to superclasses and metaclasses cls->initClassIsa(meta); if (superclass) { meta->initClassIsa(superclass->ISA()->ISA()); cls->superclass = superclass; meta->superclass = superclass->ISA(); addSubclass(superclass, cls); addSubclass(superclass->ISA(), meta); } else {
对象的销毁
-
当我们对一个对象发送 dealloc 消息时
// Replaced by NSZombies - (void)dealloc { _objc_rootDealloc(self); } // 内部调用 void _objc_rootDealloc(id obj) { assert(obj); obj->rootDealloc(); } inline void objc_object::rootDealloc() { if (isTaggedPointer()) return; // fixme necessary? /** nonpointer代表是否开启isa指针优化。 weakly_referenced代表对象被指向或者曾经指向一个 ARC 的弱变量。 has_assoc代表对象含有或者曾经含有关联引用。 has_cxx_dtor之前提到过了,是析构器。 has_sidetable_rc判断该对象的引用计数是否过大。 */ 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 * Destroys an instance without freeing memory. * Calls C++ destructors. * Calls ARC ivar cleanup. * Removes associative references. * Returns `obj`. Does nothing if `obj` is nil. **********************************************************************/ 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(); } return obj; } -
当调用 object_cxxDestruct 方法时,后续调用如下:
/*********************************************************************** * object_cxxDestruct. * Call C++ destructors on obj, if any. * Uses methodListLock and cacheUpdateLock. The caller must hold neither. **********************************************************************/ void object_cxxDestruct(id obj) { if (!obj) return; if (obj->isTaggedPointer()) return; object_cxxDestructFromClass(obj, obj->ISA()); } /*********************************************************************** * object_cxxDestructFromClass. * Call C++ destructors on obj, starting with cls's * dtor method (if any) followed by superclasses' dtors (if any), * stopping at cls's dtor (if any). * Uses methodListLock and cacheUpdateLock. The caller must hold neither. **********************************************************************/ static void object_cxxDestructFromClass(id obj, Class cls) { void (*dtor)(id); // Call cls's dtor first, then superclasses's dtors. 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); } } } /*********************************************************************** * object_cxxDestructFromClass. * Call C++ destructors on obj, starting with cls's * dtor method (if any) followed by superclasses' dtors (if any), * stopping at cls's dtor (if any). * Uses methodListLock and cacheUpdateLock. The caller must hold neither. **********************************************************************/ static void object_cxxDestructFromClass(id obj, Class cls) { void (*dtor)(id); // Call cls's dtor first, then superclasses's dtors. for ( ; cls; cls = cls->superclass) { if (!cls->hasCxxDtor()) return; dtor = (void(*)(id)) // 从子类开始沿着继承链一直找到父类,向上搜寻 SEL_cxx_destruct 这个selector,找到函数实现(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); } } } -
当调用 _object_remove_assocations 方法时,后续调用如下:
void _object_remove_assocations(id object) { vector< ObjcAssociation,ObjcAllocator<ObjcAssociation> > elements; { AssociationsManager manager; AssociationsHashMap &associations(manager.associations()); if (associations.size() == 0) return; disguised_ptr_t disguised_object = DISGUISE(object); AssociationsHashMap::iterator i = associations.find(disguised_object); if (i != associations.end()) { // copy all of the associations that need to be removed. ObjectAssociationMap *refs = i->second; for (ObjectAssociationMap::iterator j = refs->begin(), end = refs->end(); j != end; ++j) { elements.push_back(j->second); } // remove the secondary table. delete refs; associations.erase(i); } } // the calls to releaseValue() happen outside of the lock. for_each(elements.begin(), elements.end(), ReleaseValue()); } -
至此,对象被销毁
总结
- 此次关于对象生命周期的源码分析到这里就结束了,由于时间和精力有限,这里只做了一个大概的了解,并没有特别深入的研究,希望有不同意见和建议的大佬们能够不吝赐教,谢谢!