zoukankan      html  css  js  c++  java
  • JVM中java类的载入时机

    Java虚拟机把描写叙述类的数据从Class文件载入到内存。并对数据进行校验、转换解析和初始化。终于形成能够被虚拟机直接使用的Java类型。这就是虚拟机的载入机制。
    类从被载入到虚拟机内存中開始,到卸载出内存为止。它的整个生命周期包含了:载入(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(using)、和卸载(Unloading)七个阶段。

    当中验证、准备和解析三个部分统称为连接(Linking),例如以下如所看到的。


    这七个阶段,载入、验证、准备、初始化和卸载这五个阶段的顺序是确定的。类的载入过程必须依照这个顺序来按部就班地開始,而解析阶段则不一定,它在某些情况下能够在初始化阶段后再開始。

    类的生命周期的每个阶段通常都是互相交叉混合式进行的。一般会在一个阶段运行的过程中调用或激活另外一个阶段。


    Java虚拟机规范没有强制性约束在什么时候開始类载入过程。可是对于初始化阶段,虚拟机规范则严格规定了有且仅仅有四种情况必需马上对类进行“初始化”(而载入、验证、准备阶段则必需在此之前開始)。这四种情况归类例如以下:

    1.遇到new、getstatic、putstatic或invokestatic这4条字节码指令时。假设类没有进行过初始化,则须要先触发其初始化。生成这4条指令最常见的Java代码场景是:使用newkeyword实例化对象时、读取或者设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)时、以及调用一个类的静态方法的时候。
    2.使用java.lang.reflect包的方法对类进行反射调用的时候。假设类没有进行过初始化,则须要先触发其初始化。
    3.当初始化一个类的时候,假设发现其父类还没有进行过初始化,则须要触发父类的初始化。


    4.当虚拟机启动时,用户须要指定一个运行的主类(包括main()方法的类),虚拟机会先初始化这个类。
    对于这四种触发类进行初始化的场景,在java虚拟机规范中限定了“有且仅仅有”这四种场景会触发。这四种场景的行为称为对类的主动引用,除此以外的全部引用类的方式都不会触发类的初始化,称为被动引用。

    以下通过三个实例来说明被动引用:

    演示样例1:

    父类SuperClass.java 
    public class SuperClass {  
        static{  
             System.out.println("SuperClass init!");  
          }  
         public static int value = 123;  
    }  
    子类SubClass.java
         public class SubClass extends SuperClass {  
         static{  
            System.out.println("SubClass init!");  
        }  
    }  
     
    主类NotInitialization.java
    public class NotInitialization {  
        public static void main(String[] args) {  
            System.out.println(SubClass.value);  
        }  
    }  
    输出结果:
    
    SuperClass init! 
    
    123  
    
    


    由结果能够看出仅仅输出了“SuperClass init!

    ”,没有输出“SubClass init。”。这是由于对于静态字段,仅仅有直接定义该字段的类才会被初始化。因此当我们通过子类来引用父类中定义的静态字段时,仅仅会触发父类的初始化,而不会触发子类的初始化。

    演示样例2:

    SuperClass[ ]   scs=new SuperClass[11];


    如上。当初始化一个对象数组的时候。也不会触发类的初始化。

    演示样例3:

    public class ConstClass {
    
       static {
    
        system.out.printl("const");
    
    }
    
       public static final int age =123;  
    
    }
    
    public class NotInitialization{
    
         public static void main(String[ ] args){
    
         system.out.println(ConstClass.age);
    
    }

    此时并不会出现 “const”,由于在NotInitialization类在编译的时候已经把ConstClass中的变量age放在常量池中了,訪问时直接取出age就可以。不会引发ConstClass的初始化。

     

  • 相关阅读:
    GET和POST区别
    es索引介绍
    前端 用法记录
    axios 使用
    react技巧 学习
    vuex 学习笔记
    fetch 学习笔记
    react-router 4.0 学习笔记
    react 学习笔记2
    react 学习笔记
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6920119.html
Copyright © 2011-2022 走看看