zoukankan      html  css  js  c++  java
  • JAVA-类加载机制(1)-生命周期

    一,类加载机制是什么?

    将包含类数据的Class文件加载到内存,进行校验,解析,初始化之后,形成可被虚拟机直接使用的java类型;

    主要内容:

      ①,全盘负责:当类加载器加载一个类时,这个类所依赖的引用的其他类都由同一个类加载器加载,除非显示使用其他类加载器加载

      ②,父类委托:先让父类加载器加载该类,如果父类无法加载,再尝试加载该类

        ③,缓存机制:加载过的class会被缓存起来,当使用class的时候先从缓存中查找,如果找不到系统才会读取类的二进制字节流,并将其转换为Class对象,存入缓存

              (因此修改了类后需要重启JVM)

              

    二,类的生命周期

        

    1,加载:获取类的字节流,内存中创建java.lang.Class对象

    2,验证: 对文件格式,元数据,字节码,符号引用验证

    3,准备: 在方法区对静态变量分配内存,并设置初始零值

    4,解析: 常量池中的符号引用转为直接引用

    5,初始化: 再次初始化类变量和其他资源, 如静态变量设置正确的初始值

    6,使用: 使用new出的对象在程序中的使用

    7,卸载: 执行垃圾回收

    这5个阶段是按照上面的顺序开始的,但是不一定按照上面的顺序进行或者完成,各个阶段相互交叉混合进行的,一个阶段执行过程中会激活其他阶段

    其他扩展:

       有且只有以下5种情况下发现有未初始化的类将会触发类的“初始化”:         <------这5种行为引用类的方式称为:对类的"主动引用",其他引用类的方式被称为"被动引用"

      【1】,①使用new实例化对象  

         ②读取设置静态字段(static;   但是除外(final修饰已在编译期放入常量池的静态字段,本质上没有引用到定义常量的类))  

         ③调用静态方法

      【2】,使用反射(对类使用java.lang.reflect包的方法进行反射调用对应的类未初始化)

      【3】,父类未初始化     (如果是接口:则只有真正使用到父类接口时才初始化,其他4中情况都相同)

      【4】,虚拟机启动对主类初始化(包含main方法的类)

      【5】,使用动态语言(如:使用JDK1.7动态语言,java.lang.invoke.MethodHandle实例后的REF_getStatic等方法句柄对应的类未初始化)

    被动引用例子(一):

      

    package com.classload.temp;
    /**
     * 父类
     */
    public class SuperClass {
    
    //类使用static输出类的初始化信息; 接口由编译器自动生成<clinit>()类构造器,初始化接口的成员变量
    static { System.out.println("SuperClass init ... ... "); } public static int value = 123; }
    package com.classload.temp;
    /**
     * 子类
     */
    public class SubClass extends SuperClass {
        
        static {
            System.out.println("SubClass init ... ... ");
        }
        
    }
    package com.classload.temp;
    
    public class MainTest {
        
        /**
         * 通过子类引用父类静态字段
         *   子类不会初始化(不属于主动引用),
         *   父类进行初始化(属于主动引用: 符合主动引用第1,3条规则)
         */
        public static void main(String[] args) {
            System.out.println(SubClass.value);
        }
        
        /**
         * 运行结果: 
         * SuperClass init ... ... 
           123
         */
    
    }

    被动引用例子(二):

    package com.classload.temp;
    
    public class MainTest {
        
        /**
         * 通过数组定义引用类
         * 不属于主动引用,类不会初始化
         */
        public static void main(String[] args) {
            SuperClass[] arr = new SuperClass[10];
        }

      //运行结果为空 }

    被动引用例子(三):

    package com.classload.temp;
    
    public class ConstClass {
    
        static {
            System.out.println("ConstClass init ... ... ");
        }
        
        //该静态常量在编译期存入常量池
        public static final String HELLOWORLD = "hello world";
    }
    package com.classload.temp;
    
    public class MainTest {
        
        /**
         * 使用final修饰的静态常量
         * HELLOWORLD常量在编译期存入了MainTest类常量池,不会初始化ConstClass类(不符合主动引用第1条规则)
         * 如果ConstClass.HELLOWORLD只使用static修饰(符合主动引用第1条规则属于主动引用)则会进行ConstClass类初始化
         */
        public static void main(String[] args) {
            System.out.println(ConstClass.HELLOWORLD);
        }
        
    }

       

     参考:http://www.importnew.com/23742.html

     参考:《深入理解Java虚拟机》

  • 相关阅读:
    第二课:部署Kubenetes集群部署-二进制安装
    第一课:Kubernets基本介绍和集群部署-准备工作
    docker系统初始化脚本
    第六课:docker-swarm
    第八课:docker图形化界面管理-Portainer
    ssh 解决远程桌面端口问题
    ssh反向通信
    gui的服务器和vnc安装测试
    Redis Cluster集群架构实现
    端口banner信息获取
  • 原文地址:https://www.cnblogs.com/wanhua-wu/p/6557576.html
Copyright © 2011-2022 走看看