美文网首页
iOS类的加载

iOS类的加载

作者: SurpleXie | 来源:发表于2020-10-16 16:57 被阅读0次
    1、镜像加载:read_images
    • _objc_init注入回调_dyld_objc_notify_register(&map_images, load_images, unmap_image) 可知镜像的加载在map_images中
      if (hCount > 0) {
            _read_images(hList, hCount, totalClasses, unoptimizedTotalClasses);# _read_images
        }
    
        firstTime = NO;
        
        // Call image load funcs after everything is set up.
        for (auto func : loadImageFuncs) {
            for (uint32_t i = 0; i < mhCount; i++) {
                func(mhdrs[i]);
            }
        }
    

    read_images主要功能有:

      1. 条件控制进行一次的加载
      1. 修复预编译阶段的 @selector 的混乱问题
      1. 错误混乱的类处理
      1. 修复重映射一些没有被镜像文件加载进来的 类
      1. 修复一些消息!
      1. 当我们类里面有协议的时候 : readProtocol
      1. 修复没有被加载的协议
      1. 分类处理
      1. 类的加载处理
    • 10.没有被处理的类 优化那些被侵犯的类
    2、类的加载

    点击进入read_images方法

    void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses)
    

    在该方法中我们可以找到

    // Discover classes. Fix up unresolved future classes. Mark bundle classes.
    
    discoverClass.jpg

    classref_t const *classlist = _getObjc2ClassList(hi, &count);获取到classList,然后遍历classlist 进行类的加载。
    再往下,我们会发现有个Realize non-lazy classes非懒加载类

    // Realize non-lazy classes (for +load methods and static instances)
        for (EACH_HEADER) {
            classref_t const *classlist = 
                _getObjc2NonlazyClassList(hi, &count);
            for (i = 0; i < count; i++) {
                Class cls = remapClass(classlist[i]);
                
                const char *mangledName  = cls->mangledName();
                const char *LGPersonName = "LGPerson";
               
                if (strcmp(mangledName, LGPersonName) == 0) {
                    auto kc_ro = (const class_ro_t *)cls->data();
                    printf("_getObjc2NonlazyClassList: 这个是我要研究的 %s \n",LGPersonName);
                }
                
                if (!cls) continue;
    
                addClassTableEntry(cls);
    
                if (cls->isSwiftStable()) {
                    if (cls->swiftMetadataInitializer()) {
                        _objc_fatal("Swift class %s with a metadata initializer "
                                    "is not allowed to be non-lazy",
                                    cls->nameForLogging());
                    }
                    // fixme also disallow relocatable classes
                    // We can't disallow all Swift classes because of
                    // classes like Swift.__EmptyArrayStorage
                }
                realizeClassWithoutSwift(cls, nil);
            }
        }
    

    在方法中,我们可以看到 realizeClassWithoutSwift(cls, nil)方法,这个是方法加载的重中之重,点击 realizeClassWithoutSwift(cls, nil)进入查看源代码

    static Class realizeClassWithoutSwift(Class cls, Class previously)
    {
        runtimeLock.assertLocked();
    
        class_rw_t *rw;
        Class supercls; //父类
        Class metacls; //元类
        
        const char *mangledName  = cls->mangledName();
        const char *LGPersonName = "LGPerson";
    
        if (strcmp(mangledName, LGPersonName) == 0) {
            auto kc_ro = (const class_ro_t *)cls->data();
            auto kc_isMeta = kc_ro->flags & RO_META;
            if (!kc_isMeta) {
                printf("%s: 这个是我要研究的 %s \n",__func__,LGPersonName);
            }
        }
    
        if (!cls) return nil;
        if (cls->isRealized()) return cls;
        ASSERT(cls == remapClass(cls));
    
        // fixme verify class is not in an un-dlopened part of the shared cache?
       //ro 和rw的赋值
        auto ro = (const class_ro_t *)cls->data();
        auto isMeta = ro->flags & RO_META;
        if (ro->flags & RO_FUTURE) {
            // This was a future class. rw data is already allocated.
            rw = cls->data();
            ro = cls->data()->ro();
            ASSERT(!isMeta);
            cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
        } else {
            // Normal class. Allocate writeable class data.
            rw = objc::zalloc<class_rw_t>();
            rw->set_ro(ro);
            rw->flags = RW_REALIZED|RW_REALIZING|isMeta;
            cls->setData(rw);
        }
    
    #if FAST_CACHE_META
        if (isMeta) cls->cache.setBit(FAST_CACHE_META);
    #endif
    
        // Choose an index for this class.
        // Sets cls->instancesRequireRawIsa if indexes no more indexes are available
        cls->chooseClassArrayIndex();
    
        if (PrintConnecting) {
            _objc_inform("CLASS: realizing class '%s'%s %p %p #%u %s%s",
                         cls->nameForLogging(), isMeta ? " (meta)" : "", 
                         (void*)cls, ro, cls->classArrayIndex(),
                         cls->isSwiftStable() ? "(swift)" : "",
                         cls->isSwiftLegacy() ? "(pre-stable swift)" : "");
        }
    
        // Realize superclass and metaclass, if they aren't already.
        // This needs to be done after RW_REALIZED is set above, for root classes.
        // This needs to be done after class index is chosen, for root metaclasses.
        // This assumes that none of those classes have Swift contents,
        //   or that Swift's initializers have already been called.
        //   fixme that assumption will be wrong if we add support
        //   for ObjC subclasses of Swift classes.
        supercls = realizeClassWithoutSwift(remapClass(cls->superclass), nil);
        metacls = realizeClassWithoutSwift(remapClass(cls->ISA()), nil);
    
    #if SUPPORT_NONPOINTER_ISA
        if (isMeta) {
            // Metaclasses do not need any features from non pointer ISA
            // This allows for a faspath for classes in objc_retain/objc_release.
            cls->setInstancesRequireRawIsa();
        } else {
            // Disable non-pointer isa for some classes and/or platforms.
            // Set instancesRequireRawIsa.
            bool instancesRequireRawIsa = cls->instancesRequireRawIsa();
            bool rawIsaIsInherited = false;
            static bool hackedDispatch = false;
    
            if (DisableNonpointerIsa) {
                // Non-pointer isa disabled by environment or app SDK version
                instancesRequireRawIsa = true;
            }
            else if (!hackedDispatch  &&  0 == strcmp(ro->name, "OS_object"))
            {
                // hack for libdispatch et al - isa also acts as vtable pointer
                hackedDispatch = true;
                instancesRequireRawIsa = true;
            }
            else if (supercls  &&  supercls->superclass  &&
                     supercls->instancesRequireRawIsa())
            {
                // This is also propagated by addSubclass()
                // but nonpointer isa setup needs it earlier.
                // Special case: instancesRequireRawIsa does not propagate
                // from root class to root metaclass
                instancesRequireRawIsa = true;
                rawIsaIsInherited = true;
            }
    
            if (instancesRequireRawIsa) {
                cls->setInstancesRequireRawIsaRecursively(rawIsaIsInherited);
            }
        }
    // SUPPORT_NONPOINTER_ISA
    #endif
    
        // Update superclass and metaclass in case of remapping
        cls->superclass = supercls;
        cls->initClassIsa(metacls);
    
        // Reconcile instance variable offsets / layout.
        // This may reallocate class_ro_t, updating our ro variable.
        if (supercls  &&  !isMeta) reconcileInstanceVariables(cls, supercls, ro);
    
        // Set fastInstanceSize if it wasn't set already.
        cls->setInstanceSize(ro->instanceSize);
    
        // Copy some flags from ro to rw
        if (ro->flags & RO_HAS_CXX_STRUCTORS) {
            cls->setHasCxxDtor();
            if (! (ro->flags & RO_HAS_CXX_DTOR_ONLY)) {
                cls->setHasCxxCtor();
            }
        }
        
        // Propagate the associated objects forbidden flag from ro or from
        // the superclass.
        if ((ro->flags & RO_FORBIDS_ASSOCIATED_OBJECTS) ||
            (supercls && supercls->forbidsAssociatedObjects()))
        {
            rw->flags |= RW_FORBIDS_ASSOCIATED_OBJECTS;
        }
    
        // Connect this class to its superclass's subclass lists
        if (supercls) {
            addSubclass(supercls, cls);
        } else {
            addRootClass(cls);
        }
    
        // Attach categories
        methodizeClass(cls, previously);
    
        return cls;
    }
    

    ro 和rw的赋值

    rw = objc::zalloc<class_rw_t>();
    rw->set_ro(ro);
    rw->flags = RW_REALIZED|RW_REALIZING|isMeta;
    cls->setData(rw);
    

    cls->父类->元类:cls LGPerson递归实现继承链和元类链

    supercls = realizeClassWithoutSwift(remapClass(cls->superclass), nil);
    metacls = realizeClassWithoutSwift(remapClass(cls->ISA()), nil);
    

    在main函数中调用 LGPerson *person = [LGPerson alloc]之后,才调用reaizeClassWithoutSwift,reaizeClassWithoutSwift的调用时机是在消息发送的慢速查找lookUpImpOrForward中,消息发送之前会先判断类是否实现,cls = initializeAndLeaveLocked(cls, inst, runtimeLock)----这是OC中著名的懒加载机制,将类的加载推迟到第一次方法调用的时候。

    相关文章

      网友评论

          本文标题:iOS类的加载

          本文链接:https://www.haomeiwen.com/subject/zyozpktx.html