美文网首页
12、类的加载分析

12、类的加载分析

作者: ChenL | 来源:发表于2020-10-16 16:35 被阅读0次

上篇已经说明了 map_images,但没有详细说明,下面我们来继续..

1、_read_images分析

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

void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses)
{
      里面的代码太多,就不一一说明了
}
// Discover classes. Fix up unresolved future classes. Mark bundle classes.
    bool hasDyldRoots = dyld_shared_cache_some_image_overridden();

    for (EACH_HEADER) {
        if (! mustReadClasses(hi, hasDyldRoots)) {
            // Image is sufficiently optimized that we need not call readClass()
            continue;
        }

        classref_t const *classlist = _getObjc2ClassList(hi, &count);

        bool headerIsBundle = hi->isBundle();
        bool headerIsPreoptimized = hi->hasPreoptimizedClasses();

       //确定类的继承关系
        for (i = 0; i < count; i++) {
            Class cls = (Class)classlist[i];
            Class newCls = readClass(cls, headerIsBundle, headerIsPreoptimized);

            if (newCls != cls  &&  newCls) {
                // Class was moved but not deleted. Currently this occurs 
                // only when the new class resolved a future class.
                // Non-lazily realize the class below.
                resolvedFutureClasses = (Class *)
                    realloc(resolvedFutureClasses, 
                            (resolvedFutureClassCount+1) * sizeof(Class));
                resolvedFutureClasses[resolvedFutureClassCount++] = newCls;
            }
        }
    }

2、readClass 分析

由上可以得到 cls 和 类名 关联起来..

image.png

增加条件判断--指定判断类

image.png
这个if语句肯定不会走的
    if (headerIsPreoptimized  &&  !replacing) {
        // class list built in shared cache
        // fixme strict assert doesn't work because of duplicates
        // ASSERT(cls == getClass(name));
        ASSERT(getClassExceptSomeSwift(mangledName));
    } else {

 那直接来到了这里了..
        addNamedClass(cls, mangledName, replacing);
        addClassTableEntry(cls);
    }

addNamedClass,给了cls名字

image.png

3、addNamedClass 方法分析

static void addNamedClass(Class cls, const char *name, Class replacing = nil)
{
    runtimeLock.assertLocked();
    Class old;
    if ((old = getClassExceptSomeSwift(name))  &&  old != replacing) {
        inform_duplicate(name, old, cls);

        // getMaybeUnrealizedNonMetaClass uses name lookups.
        // Classes not found by name lookup must be in the
        // secondary meta->nonmeta table.
        addNonMetaClass(cls);
    } else {
        NXMapInsert(gdb_objc_realized_classes, name, cls);
    }
    ASSERT(!(cls->data()->flags & RO_META));

    // wrong: constructed classes are already realized when they get here
    // ASSERT(!cls->isRealized());
}
image.png

走完NXMapInsert方法之后,这个类名就关联起来了~

二、懒加载类与非懒加载类

懒加载类与非懒加载类的区别:当前类是否实现load方法(load方法在mian函数之前)

1、非懒加载类情况

map_images的时候 加载所有类数据:

  • _getObjc2NonlazyClassList
  • readClass
  • realizeClassWithoutSwift
  • methodizeClass
image.png

们也可以根据_read_images中的注释分析 ,当我们调试的时候没有走到这里,说明我们没有实现load,要是我们实现load的话是不是在这里就可以观察类的加载情况呢?

image.png image.png image.png

读取classdata数据,并将其强转为ro,以及rw初始化ro拷贝一份到rw中的ro

  • ro 表示 readOnly,即只读,其在编译时就已经确定了内存,包含类名称、方法、协议和实例变量的信息,由于是只读的,所以属于Clean Memory,而Clean Memory是指加载后不会发生更改的内存

  • rw 表示 readWrite,即可读可写,由于其动态性,可能会往类中添加属性、方法、添加协议,在最新的2020的WWDC的对内存优化的说明Advancements in the Objective-C runtime - WWDC 2020 - Videos - Apple Developer中,提到rw,其实在rw中只有10%的类真正的更改了它们的方法,所以有了rwe,即类的额外信息。对于那些确实需要额外信息的类,可以分配rwe扩展记录中的一个,并将其滑入类中供其使用。其中rw就属于dirty memory,而 dirty memory是指在进程运行时会发生更改的内存类结构一经使用就会变成 ditry memory,因为运行时会向它写入新数据,例如 创建一个新的方法缓存,并从类中指向它

我们通过断点调试,发现他走的是 realizeClassWithoutSwift(cls, nil); (实现类)

image.png image.png

递归调用realizeClassWithoutSwift完善继承链,并设置当前类、父类、元类的rw
递归调用 realizeClassWithoutSwift设置父类元类
设置父类和元类的isa指向
通过addSubclassaddRootClass设置父子的双向链表指向关系,即父类中可以找到子类,子类中可以找到父类

image.png
2、懒加载类情况

数据加载推迟到第⼀次消息的时候

  • LookUpImpOrForword
  • realizeClassMaybeSwiftMaybeRelock
  • realizeClassWithoutSwift
  • methodizeClass

我们知道非懒加载怎么加的方法属性。那么懒加载呢?(把load去掉,然后调用一波),我们可以通过bt,或者 看堆栈

image.png

总结:

image.png

相关文章

  • 12、类的加载分析

    上篇已经说明了 map_images,但没有详细说明,下面我们来继续.. 1、_read_images分析 1、条...

  • Tomcat之类加载器

    分析Tomcat是避不开tomcat的类加载机制 类加载器 Java中的类遵循按需加载。类加载器:就是用于加载 J...

  • Tomcat源码分析 -- Tomcat类加载器

    本章结构如下: 前言 Java类加载机制 tomcat类加载器 tomcat类加载器源码分析 一、前言 下载tom...

  • JVM类加载和双亲委派机制

    类加载器 类加载器的作用就是把磁盘中的类文件加载到内存的方法区以供使用,分析类加载前,先看下jvm运行时都需要加载...

  • 03 解读 java类加载

    分析java类加载过程 类加载主要是由jvm虚拟机负责的,过程就可以分为 编译 >>> 类加载 >>> 初...

  • 类的加载分析

    关于map_images的讲解之 类信息非常重要的方法 1.readClass读取内存里的数据,然后再插入表中 2...

  • 从jdk源码深入剖析java类加载机制

    类加载过程整体分析 当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到 JV...

  • 类的加载(下)

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

  • java面试一日一题:讲下在什么情况下会发生类加载

    问题:请讲下在什么情况下会发生类加载? 分析:该问题主要考察对java中类加载的知识,什么是类加载,为什么会发生类...

  • ClassLoader双亲委派机制源码分析

    前言:为了更好的分析Tomcat的类加载机制,首先要对JDK的类加载机制有较为深入的理解,JDK类加载机制的前期理...

网友评论

      本文标题:12、类的加载分析

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