jvm类加载_类的流程

Posted liweibing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jvm类加载_类的流程相关的知识,希望对你有一定的参考价值。

类的流程

 

      

       技术图片

 

      类的加载流程各阶段说明:

         全限定名 : 包名 + 类名

         加载 :  1. 根据类的全限定名找到对应的二进制流

                    2. 将静态数据结构转换为方法区运行时数据结构

                    3. 在堆中生成一个java.lang.class对象,作为访问方法区这些数据的入口

          验证 : 校验字节码正确性 和 二进制流正确性等,其目的就是为了保证jvm的正确运行.

          准备 : 为类中的静态变量准备分配内存,并赋予其默认值

                   如 int a = 5 .  Integer b = 10 . 在这里 a =0 , b =null  . 在真正初始化的时候才会为其赋予真正的值

                   常量的初值即为代码中设置的值,final static tmp = 456, 那么该阶段tmp的初值就是456

          解析 : 将类中的符号引用转换为直接引用

                     符号引用 : 一个字符串,但是这个字符串给出了可以唯一识别一个类,方法,变量的相关信息

                     直接引用 : 可以理解为内存地址或者偏移量 . 当为一个类变量或者类方法时, 直接引用代表指向方法区的一个指针 . 当为实例时,直接引用代表 从这个实例的头指针算起,到这个实例位置的偏移量.

                     在此阶段,虚拟机会把次类中的方法名,变量名,类名这些符号引用转换为直接引用.

          初始化 :  执行构造器 <client>方法 . 换句话说, 这个时候只对 类变量或者静态代码块进行初始化

                     如 上面的 a此时值为5 , b = 10

                     如果存在多个静态变量或者静态代码块,从上至下顺序执行.

                     此阶段,如果发现此类存在父类,且父类未进行初始化,则优先初始化父类

 

Java虚拟机规范中严格规定了以下情况必须对类进行初始化:

       

       1. 直接new此对象的实例

       2. 对一个类的静态变量进行读取或者重新赋值

       3. 虚拟机启动时,  把此类作为执行的主类

       4. 通过java.lang.reflect 对此类进行反射 (其实反射好像也是通过调用构造方法来初始化得到的对象)

       5. 初始化一个类的子类

 

示例 :

 

//父类  
public class SuperClass {  
    //静态变量value  
    public static int value = 666;  
    //静态块,父类初始化时会调用  
    static{  
        System.out.println("父类初始化!");  
    }  
}  
 
//子类  
public class SubClass extends SuperClass{  
    //静态块,子类初始化时会调用  
    static{  
        System.out.println("子类初始化!");  
    }  
}  
 
//主类、测试类  
public class NotInit {  
    public static void main(String[] args){  
        System.out.println(SubClass.value);  
    }  
}

 

输出 :  父类初始化!  666

 

        1. 静态常量在编译阶段就会被存入调用类的常量池中,不会引用到定义常量的类,这是一个特例,需要特别记忆,不会触发类的初始化!

 



    //父类  
 
   public class SuperClass {  
        //静态变量value  
        public static int value = 666;  
        //静态块,父类初始化时会调用  
        static{  
            System.out.println("父类初始化!");  
        }  
    }  
      
    //主类、测试类  
    public class NotInit {  
        public static void main(String[] args){  
            SuperClass[] test = new SuperClass[10];  
        }  
    }  

输出 :  什么也没有

 

        2. 通过数组来引用类,不会触发类的初始化,因为是数组new,而类没有被new

 

 

 

                     

 

 

 

 

     

 

         

以上是关于jvm类加载_类的流程的主要内容,如果未能解决你的问题,请参考以下文章

Day324.类加载子系统 -JVM

JVM_11 类加载与字节码技术 (类加载与类的加载器)

JVM_11 类加载与字节码技术 (类加载与类的加载器)

JVM16_类的概述分类ClassLoader源码分析自定义类的加载器双亲委派机制沙箱安全机制

JVM02_类加载子系统

浅谈JVM-图解类加载机制