美文网首页
类&分类的加载

类&分类的加载

作者: 85ca4232089b | 来源:发表于2020-03-23 11:24 被阅读0次

类的加载:

  1. libObjc 向 dyld 注册了回调 _dyld_objc_notify_register,当 dyld 把 App 以及 App 所依赖的一系列 Mach-O 镜像加载到当前 App 被分配的内存空间之后,dyld 会通过 _dyld_objc_notify_mapped 也就是 map_images 来通知 libObjc 来完成具体的加载工作,map_images 被调用之后会来到 _read_images
  2. 插入所有的类 到 gdb_objc_realized_classes 哈希表中(插入方式为 类名为 key,类对象为value, 不包括通过 共享缓存 里面的类),同时还会把类插入到 allocatedClasses 这个集合里面,注意,allocatedClasses 的类型为 NXHashTable,可以类比为 NSSet,而 gdb_objc_realized_classes 的类型为 NXMapTable,可以类比为 NSDictionary
  3. 将所有的 Protocol 插入到 readProtocol 哈希表中(插入方式为:Protocol 名称为 key,Protocol 为 value)
  4. 将所有的 SEL 插入到 namedSelectors 哈希表中(插入方式为:SEL 名称为 key,SEL 为value)

• 懒加载类
在第一次发送某个消息的时候,是没有缓存的,所以会来到一个非常重要的方法叫 lookUpImpOrForward

    if (slowpath(!cls->isRealized())) {
        cls = realizeClassMaybeSwiftAndLeaveLocked(cls, runtimeLock);
        // runtimeLock may have been dropped but is now locked again
    }

if (slowpath(!cls->isRealized())) {
slowpath小概率事件:意思是cls有很小的概率是没有实现的
• 类第一次发送消息的时候是没有缓存的,所以会来到 _class_lookupMethodAndLoadCache3
• _class_lookupMethodAndLoadCache3 会调用 lookUpImpOrForward
• lookUpImpOrForward 内部会进行一下判断,如果 cls 没有被实现,会调用 realizeClassMaybeSwiftAndLeaveLocked 方法
• realizeClassMaybeSwiftAndLeaveLocked 方法又会调用 realizeClassMaybeSwiftMaybeRelock 方法
• realizeClassMaybeSwiftMaybeRelock 方法内部会进行一下是否是 Swift 的判断,如果不是 Swift 环境的话,就会来到 realizeClassWithoutSwift ,也就是最终的类的加载的地方

• 非懒加载类

    // Realize non-lazy classes (for +load methods and static instances)实现非懒加载类(实现了 +load 方法和静态实例)
    for (EACH_HEADER) {
        classref_t const *classlist = 
            _getObjc2NonlazyClassList(hi, &count);
        for (i = 0; i < count; i++) {
            Class cls = remapClass(classlist[i]);
            if (!cls) continue;
            printf("_getObjc2NonlazyClassList Class:%s\n",cls->mangledName());
            
            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());
                }
            }
            realizeClassWithoutSwift(cls, nil);
        }
    }

分类的加载

• 懒加载分类
分类直接在编译时加载到了类的 ro 里面,然后在运行时被拷贝到了类的 rw 里面.
分类的加载其实跟类的懒加载与否并没有关系,也就是说懒加载的分类都是在编译时期被加载的。

• 非懒加载分类&懒加载类
走的不是发送消息的流程,而走的是 load_images 里面的 prepare_load_methods 方法

void prepare_load_methods(const headerType *mhdr)
{
    size_t count, i;

    runtimeLock.assertLocked();

    classref_t const *classlist = 
        _getObjc2NonlazyClassList(mhdr, &count);
    for (i = 0; i < count; i++) {
        schedule_class_load(remapClass(classlist[i]));
    }

    category_t * const *categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
    for (i = 0; i < count; i++) {
        category_t *cat = categorylist[i];
        Class cls = remapClass(cat->cls);
        if (!cls) continue;  // category for ignored weak-linked class
        if (cls->isSwiftStable()) {
            _objc_fatal("Swift class extensions and categories on Swift "
                        "classes are not allowed to have +load methods");
        }
        realizeClassWithoutSwift(cls, nil);
        ASSERT(cls->ISA()->isRealized());
        add_category_to_loadable_list(cat);
    }
}

调用了 realizeClassWithoutSwift 方法来加载类的。而上面的 _getObjc2NonlazyCategoryList 方法显示就是获取的所有的非懒加载分类,然后遍历这些非懒加载分类,然后去加载这些分类所依赖的类。非懒加载分类让我们的懒加载类实现提前了,懒加载类并不一定只会在第一次消息发送的时候加载,还要取决于有没有非懒加载的分类,如果有非懒加载的分类,那么就走的是 load_images 里面的 prepare_load_methods 的 realizeClassWithoutSwift 。
• 非懒加载分类&非懒加载类
attachCategories 这个方法只会在实现了 load 方法的分类下才会被调用,而来到 attachCategories 之前又取决于类是否为懒加载,如果是懒加载,那么就在 load_images 里面去处理,如果是非懒加载,那么就在 map_images 里面去处理。

总结

• 没有实现 load 方法的分类由编译时确定
• 实现了 load 方法的分类由运行时去确定

• 懒加载分类 + 懒加载类
 类的加载在第一次消息发送的时候,而分类的加载则在编译时load_images
• 懒加载分类 + 非懒加载类
  类的加载在 _read_images 处,分类的加载还是在编译时load_images
• 非懒加载分类 + 懒加载类
  类的加载在 load_images 内部,分类的加载在类加载之后的 methodizeClass
• 非懒加载分类 + 非懒加载类
  类的加载在 _read_images 处,分类的加载在类加载之后的 reMethodizeClass
消息查找流程.jpg

相关文章

  • iOS底层原理19:类和分类的加载

    前面已经探究了类的加载流程,类分为懒加载类和非懒加载类,他们有不同加载流程,下面来探究下分类的加载,以及分类和类搭...

  • 反射

    类加载器:加载过程 加载,连接,初始化 分类: Bootstrap ClassLoader 根类加载器:核心类的加...

  • 【深入理解Java虚拟机 】类的加载器

    1. 类加载器的分类 JVM 自带的类加载器 根类加载器( BootStrap ) 拓展类加载器 ( Extens...

  • 类的加载(下)

    上篇文章我们了解了类的加载和分类的数据准备 这篇我们继续分析分类的加载时机以及是如何加载到类中的 当类加载时,进入...

  • iOS开发中 +load 和 +initialize特点

    + load方法 在程序启动时,会加载所有的类和分类,并调用所有类和分类的 + load方法 先加载父类,再加载子...

  • Java高级篇——深入浅出Java类加载机制

    ​类加载器 简单讲,类加载器ClassLoader的功能就是负责将class文件加载到jvm内存。 类加载器分类 ...

  • 热修复类加载项目实战

    android 与 java 的类加载器 类别加载文件类加载器分类java.class 文件{{java类加载机制...

  • iOS之学习总结

    一、load 方法 1、load方法加载 +Load方法会在runtime加载类、分类时调用 每个类、分类的+lo...

  • JVM(四)-类加载器

    类加载器大的分类分为两类(JAVA虚拟机规范):引导类加载器、自定义类加载器 引导类加载器(启动类加载器) Boo...

  • OC底层原理探索—类的加载(3)

    上一篇我们探索了类的加载流程等一系列方法以及懒加载类和非懒加载类这节课我们来探索下分类的加载流程 分类的本质 首先...

网友评论

      本文标题:类&分类的加载

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