JVM(一) 类加载过程

177 阅读3分钟

什么是类加载器: 就是将xxx.java文件编译成的xxx.class文件加载到jvm虚拟机内存中。
一个类在什么时候开始被加载,《Java虚拟机规范》中并没有进行强制约束,交给了虚拟机自己去自由实现,HotSpot虚拟机是按需加载,在需要用到该类的时候加载这个类。

一个类从加载到jvm内存,到从jvm内存卸载,它的整个生命周期会经历7个阶段: image.png

1.加载: classpath、jar包、网络、某个磁盘位置下的类的class二进制字节流读进来,在内存中生成一个代表这个类的java.lang.Class对象放入元空间,此阶段我们程序员可以干预,我们可以自定义类加载器来实现类的加载;

2.1验证: 验证Class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证虚拟机的安全; 比如检查字节码文件开头4个字节是否是0xCAFEBABE,版本检查,长度检查等。 下图是验证阶段所做的一些事情。主要是检查字节码文件是否符合jvm规范! image.png

2.2准备: 准备阶段(Preparation),简言之,为类的静态变量分配内存,并将其初始化为默认值当一个类验证通过时,虚拟机就会进入准备阶段。在这个阶段,虚拟机就会为这个类分配相应的内存空间,并设置默认初始值。Java 虚拟机为各类型变量默认的初始值如表所示: image.png 注意:Java 并不支持 boolean 类型,对于 boolean 类型,内部实现是 int,由于 int 的默认值是 0,故对应的,boolean 的默认值就是 false

注意:

  1. 这里不包含基本数据类型的字段用 static final 修饰的情况,因为 final 在编译的时候就会分配了,准备阶段会显式赋值
  2. 注意这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到 Java 堆中
  3. 在这个阶段不会像初始化阶段中那样会有初始化或者代码被执行

2.3解析: 把符号引用翻译为直接引用;将类、接口、字段和方法的符号引用转为直接引用。比如说你调用类中的某个方法,你先是的知道常量池中的将该方法在内存中的内存地址,这就是解析。 image.png

3.初始化: 当我们new一个类的对象,访问一个类的静态属性,修改一个类的静态属性,调用一个类的静态方法,用反射API对一个类进行调用,初始化当前类,其父类也会被初始化...... 那么这些都会触发类的初始化;简言之,为类的静态变量赋予正确的初始值

4.使用: 使用这个类;任何一个类在使用之前必须经过完整的加载,链接,初始化三个阶段,完成了这三个阶段我们程序员就可以使用该类了,比如new实例化这个类,调用该类的某个方法。

5.卸载: 1.该类所有的实例都已经被GC,也就是JVM中不存在该Class的任何实例; 2.加载该类的ClassLoader已经被GC; 3.该类的java.lang.Class 对象没有在任何地方被引用,如不能在任何地方通过反射访问该类的方法;

类的生命周期简单描述: Image.png