java虚拟机加载java主要分为三个阶段 加载——>链接——>初始化
1.加载阶段
主要由jvm中的类加载器对java每个类的.class文件进行加载,类加载器主要有三种
- 启动类加载器(bootstrap class loader)-------启动类加载器负责加载最为基础、最为重要的类,比如存放在 JRE 的 lib 目录下 jar 包中的类(以及由虚拟机参数 -Xbootclasspath 指定的类)
- 扩展类加载器 (extension class loader)------扩展类加载器负责加载相对次要、但又通用的类,比如存放在 JRE 的 lib/ext 目录下 jar 包中的类(以及由系统变量 java.ext.dirs 指定的类)
- 应用类加载器 (application class loader)-----应用类加载器负责加载应用程序路径下的类。
三种加载器从上到下为继承关系:应用类加载器 extend 扩展类加载器 extend 启动类加载器
类加载的规范遵循双亲委派模型:接收到加载请求时,会先将请求转发给父类加载器,若父类加载器没有找到对应的类,则再交给子类加载器加载
双亲委派模型的好处: 保证了java程序的稳定,避免类被重复加载,JVM 区分不同类的方式不仅仅根据类名,相同的类文件被不同的类加载器加载产生的是两个不同的类。如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的 Object 类。
2.链接阶段
链接阶段主要分为:是指将创建成的类合并至 Java 虚拟机中,使之能够执行的过程。链接还分验证、准备和解析三个阶段。其中,解析阶段为非必须的
验证阶段主要是对已经加载好的类进行验证,验证这些加载好的类是否符合jvm规范
准备阶段主要是对java类的静态变量,静态块等分配内存
解析阶段主要是将java类的符号引用转为实际引用(符号引用指的是类在未加载之前jvm找到这个类的引用,实际引用指的是类在加载链接后的jvm找到该类的实际引用)
3.初始化阶段
初始化阶段主要是对常量的赋值,以及执行 < clinit > 方法的过程,< clinit > 方法中包含非常量的静态变量,静态块中的数据,执行该方法即对这些进行赋值,类的初始化仅会被执行一次,这个特性被用来实现单例的延迟初始化。