类的生命周期
类的生命周期包括加载、连接、初始化、使用和卸载。
-
加载:查找并加载类的二进制数据,在Java堆中也创建一个java.lang.Class类的对象
类由类加载器加载。启动类加载器 (BootStrap class Loader)、扩展类加载器(Extension class Loader)和应用程序类加载器(Application class Loader) 这三种类加载器帮助完成类的加载。
- 启动类加载器 – 负责从启动类路径中加载类,无非就是rt.jar。这个加载器会被赋予最高优先级。
- 扩展类加载器 – 负责加载ext 目录(jre\lib)内的类.
- 应用程序类加载器 – 负责加载应用程序级别类路径,涉及到路径的环境变量等etc.
上述的类加载器通过双亲委派机制加载类文件。
加载过程主要完成三件事情:
- 通过类的全限定名来获取定义此类的二进制字节流
- 将这个类字节流代表的静态存储结构转为方法区的运行时数据结构
- 在堆中生成一个代表此类的java.lang.Class对象,作为访问方法区这些数据结构的入口。
-
链接:链接又包含三块内容:验证、准备、初始化。
-
1)验证:文件格式、元数据、字节码、符号引用验证
文件格式验证:基于字节流验证,验证字节流符合当前的Class文件格式的规范,能被当前虚拟机处理。验证通过后,字节流才会进入内存的方法区进行存储。
元数据验证:基于方法区的存储结构验证,对字节码进行语义验证,确保不存在不符合java语言规范的元数据信息。
字节码验证:基于方法区的存储结构验证,通过对数据流和控制流的分析,保证被检验类的方法在运行时不会做出危害虚拟机的动作。字节码校验器会校验生成的字节码是否正确,如果校验失败,我们会得到校验错误。
符号引用验证:基于方法区的存储结构验证,发生在解析阶段,确保能够将符号引用成功的解析为直接引用,其目的是确保解析动作正常执行。换句话说就是对类自身以外的信息进行匹配性校验。
-
2)准备:为类的静态变量分配内存,并将其初始化为默认值;
public static int value=33;
这据代码的赋值过程分两次,一是上面我们提到的阶段,此时的value
将会被赋值为0;而value=33
这个过程发生在类构造器的<clinit>()
方法中。 -
3)解析:把类中的符号引用转换为直接引用,主要有以下四种:类或接口的解析,字段解析,类方法解析,接口方法解析。
举个例子来说明,在com.Person类中引用了com.Animal类,在编译阶段,Person类并不知道Animal的实际内存地址,因此只能用com.Animal来代表Animal真实的内存地址。在解析阶段,JVM可以通过解析该符号引用,来确定com.Animal类的真实内存地址(如果该类未被加载过,则先加载)。
-
-
初始化:类加载的最后阶段,为类的静态变量赋予正确的初始值,并且这个阶段静态块将被执行。
java中,对于初始化阶段,有且只有以下五种情况才会对要求类立刻初始化:
- 使用new关键字实例化对象、访问或者设置一个类的静态字段(被final修饰、编译器优化时已经放入常量池的例外)、调用类方法,都会初始化该静态字段或者静态方法所在的类;
- 初始化类的时候,如果其父类没有被初始化过,则要先触发其父类初始化;
- 使用java.lang.reflect包的方法进行反射调用的时候,如果类没有被初始化,则要先初始化;
- 虚拟机启动时,用户会先初始化要执行的主类(含有main);
- jdk 1.7后,如果
java.lang.invoke.MethodHandle
的实例最后对应的解析结果是REF_getStatic、REF_putStatic、REF_invokeStatic
方法句柄,并且这个方法所在类没有初始化,则先初始化;

- 使用:对象使用,创建对象的方式包括:使用 new 关键字;使用 Class 类的 newInstance 方法;使用 Constructor 类的 newInstance 方法;使用 clone 方法;使用反序列化
-
卸载:执行垃圾回收
在如下几种情况下,Java虚拟机将结束生命周期- 执行了System.exit()方法
- 程序正常执行结束
- 程序在执行过程中遇到了异常或错误而异常终止
- 由于操作系统出现错误而导致Java虚拟机进程终止

绑定本地方法实现
绑定(Binding)是指将使用 Java 之外的语言编写的函数集成到 Java 虚拟机中的过程。此函数需要实现在代码中定义好的 native 方法,之后才可以在 Java 虚拟机中运行。这个过程在传统编译原理的表述中被称“链接”,所以规范里使用“绑定”这个词就,就是为了避免与 Java 虚拟机中链接类或接口的语义发生冲突。
JVM退出
Java 虚拟机的退出条件一般是:某些线程调用 Runtime
类或 System
类的 exit
方法,或是 Runtime
类的 halt
方法,并且 Java 安全管理器也允许这些 exit
或 halt
操作。除此之外,在 JNI(Java Native Interface)
规范中还描述了当使用 JNI API
来加载和卸载(Load & Unload)
Java 虚拟机时,Java 虚拟机的退出过程。
网友评论