• Java虚拟机加载类的过程


      Java虚拟机的类加载,从class文件到内存中的类,按先后顺序需要经过加载/链接/初始化三大步骤.

      Java语言的类型分为两大类:基本类型(primitive types)和引用类型(reference types).

      Java的基本类型,是由Java虚拟机预先定义好的.

      Java的引用类型,细分为:类/接口/数组类/泛型参数. 注:泛型参数会在编译过程中被擦除,JVM实际上只有前三种.

      加载

      加载,是指查找字节流,并且据此创建类的过程. 注:数组类没有对应的字节流,而是由JVM直接生成的,而其它类则需要借助类加载器来完成查找字节流的过程.

      双亲委派模型:每当一个类加载器接收到加载请求时,它会将请求转发给父类加载器.在父类加载器没有找到所请求的类的情况下,该类加载器才会尝试去加载.

      链接

      链接,是指将创建成的类合并至Java虚拟机中,使之能够执行的过程. 分为验证/准备/解析三个阶段.

      验证阶段:确保被加载类能够满足Java虚拟机的约束条件.

      准备阶段:为被加载类的静态字段分配内存. 注:部分Java虚拟机还会在此阶段构造其它跟类层次相关的数据结构.

      解析阶段:将加载过程中对类/字段/方法声明唯一性的符号引用解析成为实际引用.如果符号引用指向一个未被加载的类,或者未被加载的字段或方法,那么解析将触发这个类的加载.

      注:Java虚拟机并没有要求在链接过程中完成解析.规定如下:如果某些字节码使用了符号引用,则在执行这些字节码前,需要完成对这些符号引用的解析.

      初始化

      pre:

        如果要初始化一个静态字段,可在声明时直接赋值,亦可在静态代码块中对其赋值.

        如果直接赋值的静态字段被final修饰,且类型为基本类型或字符串时,则该字段被Java编译器标记为常量值(Constant Value),初始化直接由Java虚拟机完成.除此之外的直接赋值操作,以及所有静态代码块中的代码,则会被Java编译器置于同一方法中,并命名为<clinit>

      初始化,为标记为常量值的字段赋值,以及执行<clinit>方法的过程. 注:Java虚拟机会通过加锁来确保类的<clinit>方法仅被执行一次.

      只有当初始化完成之后,类才正式成为可执行的状态.

      类初始化的触发时机枚举:

        1.当虚拟机启动时,初始化用户指定的主类;

        2.当遇到用以新建目标类实例的new指令时,初始化new指令的目标类;

        3.当遇到调用静态方法的指令时,初始化该静态方法所在的类;

        4.当遇到访问静态字段的指令时,初始化该静态字段所在的类;

        5.子类的初始化会触发父类的初始化;

        6.如果一个接口定义了default方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化;

        7.使用反射API对某个类进行反射调用时,初始化这个类;

        8.当初次调用MethodHandle实例时,初始化该MethodHandle指向的方法所在的类.

  • 相关阅读:
    [备份]部分常用函数
    [考试]20150904
    [考试]20150903
    [未完成][知识点]动态规划优化初步
    [考试]20150822
    [考试]20150821
    [知识点]后缀数组
    [考试]20150816
    [考试]20150815
    BZOJ2815: [ZJOI2012]灾难
  • 原文地址:https://www.cnblogs.com/nyatom/p/9370050.html
Copyright © 2020-2023  润新知