JVM类加载相关
1 双亲委托模式加载
在JVM里 类加载器接收到加载类的请求时,一般先会去查找是否已经加载过此类。findLoaderClass这个方法如图1-2所示。看看自己是否加载过此类。
1-1 1-2如果没有找到,则类加载器委托父类加载器对此类进行加载。父加载器也是先查看自己是否已经加载过此类,而后继续调用请求自己的父类。
这是一个递归查找,从子类回溯到最底层的BootClassLoader(与BootStarpClassLoader不同,BootStarpClassLoader是启动类加载器,由C++实现,除了启动类加载器之外,其他的类加载器都是 java.lang.ClassLoader 的子类,因此有对应的 Java对象。这些类加载器需要先由另一个类加载器,比如说启动类加载器,加载至 Java 虚拟机中,方能执行类加载),看是否有加载过请求类。如果BootClassLoader也没找到此类,则进行findclass(如图1-3),
findclass就将此类进行加载(最后委托BootClassLoader对类进行加载)。
1-3 1-4如果递归全返回空,既BootClassLoader的子类全未加载过请求类,且BootClassLoader也加载失败()则进行第二步,findBootStrapClass,如图1-5,这里为什么是直接返回null呢?因为所有非BootStrapClassLoader的都返回空。
1-5而后以上所有流程都走完,依旧没找到请求类。则在findClass里进行请求类的加载。
这就是双亲委托模式加载。
2 类加载流程
如何将java文件编译成为的class文件加载到JVM中.
2.1 加载
加载,是指查找字节流,并且据此创建类的过程。
2.2 链接
链接,是指将创建成的类合并至 Java 虚拟机中,使之能够执行的过程。它可分为验证、准备以及解析三个阶段。
2.2.1 验证
JVM会自动检测编译好的.class文件 是否属于JAVA文件,在class文件的开头则会有“cafe babe”字样,JVM就靠类似于这种Class文件内部一些信息确认是否是正常的.class文件
2.2.2 准备
准备阶段的目的,则是为被加载类的静态字段分配内存。除了分配内存外,部分 Java 虚拟机还会在此阶段构造其他跟类层次相关的数据结构,比如说用来实现虚方法的动态绑定的方法表.
2.2.3 解析
解析阶段的目的,将这些符号引用解析成为实际引用。如果符号引用指向一个未被加载的类,
或者未被加载类的字段或方法,那么解析将触发这个类的加载(但未必触发这个类的链接以及初始
化。)
2.3 初始化
在 Java 代码中,如果要初始化一个静态字段,我们可以在声明时直接赋值,也可以在静态代码块中对其赋值。如果直接赋值的静态字段被 final 所修饰,并且它的类型是基本类型或字符串时,那么该字段便会被 Java 编译器标记成常量值(ConstantValue),其初始化直接由 Java 虚拟机完成。除此之外的直接赋值操作,以及所有静态代码块中的代码,则会被 Java 编译器置于同一方法中,并把它命名为<cIinit> (Class Init)。
只有初始化完毕时,类才是真正的可执行状态.
网友评论