美文网首页Java工程师知识树
Java基础-JVM执行子系统-类的生命周期

Java基础-JVM执行子系统-类的生命周期

作者: HughJin | 来源:发表于2021-03-01 09:51 被阅读0次

Java工程师知识树 / Java基础


类的生命周期

类的生命周期包括加载、连接、初始化、使用和卸载

  1. 加载:查找并加载类的二进制数据,在Java堆中也创建一个java.lang.Class类的对象

    类由类加载器加载。启动类加载器 (BootStrap class Loader)、扩展类加载器(Extension class Loader)和应用程序类加载器(Application class Loader) 这三种类加载器帮助完成类的加载。

    1. 启动类加载器 – 负责从启动类路径中加载类,无非就是rt.jar。这个加载器会被赋予最高优先级。
    2. 扩展类加载器 – 负责加载ext 目录(jre\lib)内的类.
    3. 应用程序类加载器 – 负责加载应用程序级别类路径,涉及到路径的环境变量等etc.

    上述的类加载器通过双亲委派机制加载类文件。

    加载过程主要完成三件事情:

    • 通过类的全限定名来获取定义此类的二进制字节流
    • 将这个类字节流代表的静态存储结构转为方法区的运行时数据结构
    • 堆中生成一个代表此类的java.lang.Class对象,作为访问方法区这些数据结构的入口。
  2. 链接:链接又包含三块内容:验证、准备、初始化

    • 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类的真实内存地址(如果该类未被加载过,则先加载)。

  3. 初始化:类加载的最后阶段,为类的静态变量赋予正确的初始值,并且这个阶段静态块将被执行。

    java中,对于初始化阶段,有且只有以下五种情况才会对要求类立刻初始化:

    • 使用new关键字实例化对象、访问或者设置一个类的静态字段(被final修饰、编译器优化时已经放入常量池的例外)、调用类方法,都会初始化该静态字段或者静态方法所在的类;
    • 初始化类的时候,如果其父类没有被初始化过,则要先触发其父类初始化;
    • 使用java.lang.reflect包的方法进行反射调用的时候,如果类没有被初始化,则要先初始化;
    • 虚拟机启动时,用户会先初始化要执行的主类(含有main);
    • jdk 1.7后,如果java.lang.invoke.MethodHandle的实例最后对应的解析结果是 REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄,并且这个方法所在类没有初始化,则先初始化;
类加载过程
  1. 使用:对象使用,创建对象的方式包括:使用 new 关键字;使用 Class 类的 newInstance 方法;使用 Constructor 类的 newInstance 方法;使用 clone 方法;使用反序列化
  1. 卸载:执行垃圾回收
    在如下几种情况下,Java虚拟机将结束生命周期
    • 执行了System.exit()方法
    • 程序正常执行结束
    • 程序在执行过程中遇到了异常或错误而异常终止
    • 由于操作系统出现错误而导致Java虚拟机进程终止
类的生命周期

绑定本地方法实现

绑定(Binding)是指将使用 Java 之外的语言编写的函数集成到 Java 虚拟机中的过程。此函数需要实现在代码中定义好的 native 方法,之后才可以在 Java 虚拟机中运行。这个过程在传统编译原理的表述中被称“链接”,所以规范里使用“绑定”这个词就,就是为了避免与 Java 虚拟机中链接类或接口的语义发生冲突。

JVM退出

Java 虚拟机的退出条件一般是:某些线程调用 Runtime类或 System类的 exit方法,或是 Runtime类的 halt方法,并且 Java 安全管理器也允许这些 exithalt操作。除此之外,在 JNI(Java Native Interface)规范中还描述了当使用 JNI API来加载和卸载(Load & Unload)Java 虚拟机时,Java 虚拟机的退出过程。

相关文章

网友评论

    本文标题:Java基础-JVM执行子系统-类的生命周期

    本文链接:https://www.haomeiwen.com/subject/ojaufltx.html