• JVM类加载


    Java类加载

    • Java类加载需要经历5个阶段分别是加载,验证,准备,解析与初始化。

    • 类的生命周期为加载,连接,初始化,使用,卸载。

      类生命周期

    加载

    • 加载是类加载的第一个阶段,在这个阶段中,会做三件事情
      1. 通过一个类的全限定名获取该类的二进制流。(通过JVM的类加载器)。
      2. 将该二进制流中的静态存储结构转化为方法区的运行时数据结构。
      3. 在内存中生成该类的Class对象,作为访问该类生成方法区静态数据结构的访问入口。

    验证

    • 验证的目的是为了确保Class文件的字节流中的信息不会危害到JVM虚拟机,在该阶段主要完成了4种验证。
      • 文件格式验证:验证字节流是否符合Class文件的规范,如主次版本号是否在当前虚拟机范围内,常量池中的常量是否有不被支持的类型。
      • 元数据验证:对字节码描述信息进行语义分析,如和这个类是否有父类,是否继承了不被继承的类等。
      • 字节码验证:(最复杂)通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证。如:方法中的类型转换是否正确,跳转指针是否正确等。
      • 符号引用验证:在解析阶段发生,确保解析动作能正确执行。

    准备

    • 准备阶段是为了类的静态变量分配内存并将其初始化为默认值,这些内存都将分配在JVM的方法区中。准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配到JVM的堆中。

    解析

    • 解析阶段主要是完成了符号运用到直接引用的转换动作。解析动作并不一定在初始化动作完成之前,也可能发生在初始化之后。

    初始化

    • 类初始化阶段是类加载过程的最后一步。在前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的java程序代码(字节码)。

    类加载器(class loader)

    • 用来加载 Java 类到 JVM虚拟机中。VM虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。Java字节代码生成方式并不唯一: Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。但第二次实例化一个类时,就从对应Class类newInstance(),不用每次都读取.class文件。

    • 系统自带的类加载器分为三种:

      1. 启动类加载器::C++实现,在java里无法获取,负责加载/lib下的类。
      2. 扩展类加载器: Java实现,可以在java里获取,负责加载/lib/ext下的类。
      3. 应用程序类加载器:是与我们接触对多的类加载器,我们写的代码默认就是由它来加载,ClassLoader.getSystemClassLoader返回的就是它。
    • 双亲委派机制工作过程:

      • 如果一个类加载器收到了类加载的请求.它首先不会自己去尝试加载这个类.而是把这个请求委派给父加载器去完成.每个层次的类加载器都是如此.因此所有的加载请求最终都会传送到启动类加载器中.只有父类加载反馈自己无法加载这个请求(它的搜索范围中没有找到所需的类)时.子加载器才会尝试自己去加载。(特殊时候会破坏双亲委派,因为个加载器能加载的类范围不同,不同加载器加载相同类时,加载到的类不一致。)

        双亲委派机制

    类的生命周期

    • 一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段。前三个阶段与类加载过程相同。

    使用

    • 类的使用包括主动引用和被动引用。
      • 主动引用(会发生类的初始化)
        1. 通过new关键字实例化对象、读取或设置类的静态变量、调用类的静态方法;
        2. 通过反射方式执行以上三种行为;
        3. 初始化子类的时候,会触发父类的初始化;
        4. 作为程序入口直接运行时(也就是直接调用main方法)。
      • 被动引用
        1. 引用父类的静态字段,只会引起父类的初始化,而不会引起子类的初始化。
        2. 定义类数组,不会引起类的初始化。
        3. 引用类的常量,不会引起类的初始化。

    卸载

    • 在类使用完之后,如果满足下面的情况,类就会被卸载。
      1. 该类所有的实例都已经被回收,也就是JVM堆中不存在该类的任何实例;
      2. 加载该类的ClassLoader已经被回收;
      3. 该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
    • 如果以上三个条件全部满足,JVM就会在方法区垃圾回收的时候对类进行卸载,类的卸载过程是在方法区中清空类信息,java类的整个生命周期就结束了。
  • 相关阅读:
    idea设置全局ignore
    win 2012 安装mysql 5.7.20 及报错 This application requires Visual Studio 2013 Redistributable. Please ins
    win 2012 安装mysql 5.7.20 及报错 This application requires Visual Studio 2013 Redistr
    kafka 删除 topic
    java编译中出现了Exception in thread “main" java.lang.UnsupportedClassVersionError
    Centos中使用yum安装java时,没有jps的问题的解决
    Spring 整合Junit
    Spring纯注解配置
    Spring 基于注解的 IOC 配置
    打印java系统的信息
  • 原文地址:https://www.cnblogs.com/RitualYang/p/12383473.html
Copyright © 2020-2023  润新知