JVM类加载流程

类加载系统
加载 类加载器读取.class文件,生成相应的二进制数据并将其保存在方法区中。对于每个.class文件,JVM将以下信息存储在方法区中。
- 类及其直接父类的全路径名称。
- 与.class文件相关的类或接口或枚举
- 修饰符,变量和方法信息等
加载.class文件之后,JVM将创建Class类型的对象来表示该文件在堆内存中。
连接 验证 准备 解析
- 验证:确保.class文件的正确性,即检查该文件的格式是否正确,是否由有效的编译器生成。如果验证失败,我们将获得运行时异常java.lang.VerifyError。
- 准备:JVM为类变量分配内存,并将内存初始化为默认值。
- 解析:这是将类型中的符号引用替换为直接引用的过程。通过搜索方法区域以找到引用的实体来完成此操作。
初始化:在此阶段,所有静态变量都分配有在代码和静态块(如果有)中定义的值。在类中从上到下执行,在类层次结构中从上到下执行。
通常,有三种装载机:
- 引导程序类加载器:每个JVM实现都必须具有一个引导程序类加载器,能够加载受信任的类。它加载JAVA_HOME/jre/lib目录中存在的核心Java API类。该路径通常称为引导路径。它以C,C++等本地语言实现。
- 扩展类加载器:它是引导类加载器的子级。它将加载扩展目录JAVA_HOME/jre/lib/ext(扩展路径)或java.ext.dirs系统属性指定的任何其他目录中存在的类。它由sun.misc.Launcher$ExtClassLoader类在Java中实现。
- 系统/应用程序类加载器:它是扩展类加载器的子级。它负责从应用程序类路径加载类。它在内部使用映射到java.class.path的环境变量。它还由sun.misc.Launcher$AppClassLoader类在Java中实现。
注意: JVM遵循双亲委派机制加载类。系统类加载器将加载请求委托给扩展类加载器,扩展类加载器将请求委托给引导类加载器。如果在引导路径中找到了类,则将装入该类,否则再次将请求传输到扩展类加载器,然后再传输到系统类加载器。最后,如果系统类加载器无法加载类,则将获得运行时异常java.lang.ClassNotFoundException。

内存结构

堆:所有对象的信息存储在堆中。每个JVM还有一个堆。它也是共享资源。
栈: JVM为每个线程创建一个运行时栈,该栈存储在此处。此栈的每个块都称为激活记录/栈帧,用于存储方法调用。该方法的所有局部变量都存储在其相应的框架中。线程终止后,它的运行时栈将被JVM销毁。它不是共享资源。
PC寄存器:存储线程当前执行指令的地址。显然,每个线程都有单独的PC寄存器。
本机方法栈:为每个线程创建单独的本地栈。它存储本地方法信息。
参考: