Runtime源码阅读分享之对象的生命周期

484 阅读9分钟

简介

  • 这篇文章主要介绍的内容包括根据源码来理解对象从“出生”到“消亡”的整个生命周期。

对象的出生

  • 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());
    }
    
  • 至此,对象被销毁

总结

  • 此次关于对象生命周期的源码分析到这里就结束了,由于时间和精力有限,这里只做了一个大概的了解,并没有特别深入的研究,希望有不同意见和建议的大佬们能够不吝赐教,谢谢!

参考资料