• JVM


    1、内存结构

    2、GC

    3、类加载

    Java虚拟机类加载机制

    虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制。

    在Java语言里面,类型的加载、连接和初始化过程都是在程序运行期间完成的

    类的个生命周期如下图:

    为支持运行时绑定,解析过程在某些情况下可在初始化之后再开始,除解析过程外的其他加载过程必须按照如图顺序开始。

    加载
    1. 通过全限定类名来获取定义此类的二进制字节流。
    2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
    3. 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。
    验证

    验证是连接阶段的第一步,这一阶段的目的是为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

    1. 文件格式验证:如是否以魔数 0xCAFEBABE 开头、主、次版本号是否在当前虚拟机处理范围之内、常量合理性验证等。
      此阶段保证输入的字节流能正确地解析并存储于方法区之内,格式上符合描述一个 Java类型信息的要求。
    2. 元数据验证:是否存在父类,父类的继承链是否正确,抽象类是否实现了其父类或接口之中要求实现的所有方法,字段、方法是否与父类产生矛盾等。
      第二阶段,保证不存在不符合 Java 语言规范的元数据信息。
    3. 字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。例如保证跳转指令不会跳转到方法体以外的字节码指令上。
    4. 符号引用验证:在解析阶段中发生,保证可以将符号引用转化为直接引用。

    可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。

    准备

    类变量分配内存并设置类变量初始值,这些变量所使用的内存都将在方法区中进行分配。

    解析

    虚拟机将常量池内的符号引用替换为直接引用的过程。
    解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符 7 类符号引用进行。

    初始化

    到初始化阶段,才真正开始执行类中定义的 Java 程序代码,此阶段是执行 <clinit>() 方法的过程。

    <clinit>() 方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并产生的。(不包括构造器中的语句。构造器是初始化对象的,类加载完成后,创建对象时候将调用的 <init>() 方法来初始化对象)

    public class Test {
        static {
            // 给变量赋值可以正常编译通过
            i = 0;
            // 这句编译器会提示"非法向前引用"
            System.out.println(i);
        }
    
        static int i = 1;
    }

    <clinit>() 不需要显式调用父类(接口除外,接口不需要调用父接口的初始化方法,只有使用到父接口中的静态变量时才需要调用)的初始化方法 <clinit>(),虚拟机会保证在子类的 <clinit>() 方法执行之前,父类的 <clinit>() 方法已经执行完毕,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作。

    <clinit>() 方法对于类或接口来说并不是必需的,如果一个类中没有静态语句块,也没有对变量的赋值操作,那么编译器可以不为这个类生成 <clinit>() 方法。

    虚拟机会保证一个类的 <clinit>() 方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的 <clinit>() 方法,其他线程都需要阻塞等待,直到活动线程执行 <clinit>() 方法完毕。

    深入理解Java类加载 - czwbig - 博客园 (cnblogs.com)

    常量池:

    深入浅出java常量池 - 小奔的早晨 - 博客园 (cnblogs.com)

    垃圾回收:

    Java GC机制详解 - victor_tx - 博客园 (cnblogs.com)

  • 相关阅读:
    希望多年以后的自己不再如此迷茫
    【转载】撒旦(Satan 4.2)勒索病毒最新变种加解密分析
    java单例模式
    关于double/float 两种基本类型精度丢失的总结
    关于ecplise中一些很实用的技巧
    安装SQL Server和卸载SQL Server步骤
    我进入部门的第一周
    mysql数据库在Linux和windows下免安装实现以及框架开发碰到的问题
    jenkins发布docker到mesos
    u盘作为git仓库,完成不同地方的代码同步
  • 原文地址:https://www.cnblogs.com/baldprogrammer/p/14011573.html
Copyright © 2020-2023  润新知