一、概述

  1. 虚拟机加载机制

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

  2. Java是一门天生可以动态扩展的语言

    在Java语言里,类的加载、链接和初始化是在程序运行期间完成的。而C++是在编译期就开始做这些工作了。

    这种策略在类加载的时候,增加了一些内存开销。但是为Java程序提供了极高的灵活性。

    根据动态加载和动态链接,实现了Java语言的动态扩展。

    譬如: 根据预定义或者自定义的类加载器,可以加载互联网上的一个class文件,然后执行该字节码。

 

二、 类的加载时机

  1. 生命周期

    类被加载到虚拟机内存中开始,到卸载出内存位置,生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading) 7个阶段。其中, 验证、加载和解析这3个阶段称为 连接。

android 类加载原理 类加载的时机_初始化

 

  2. 运行时绑定(动态绑定或者晚期绑定)

    加载、验证、准备、初始化、卸载这5个阶段的顺序不会变的。虚拟机必须按照这个顺序来开始。

    但解析阶段则不一定,某一些情况下在初始化之后才解析阶段才开始,这是要支持java语言的运行时绑定。

    这些阶段,并不是一个阶段执行完了再执行下一个阶段,而是交替着混合着执行。可能在一个阶段中调用、激活另外一个阶段。

  

  3. 初始化的条件

    只有当满足下面5个条件之一才会执行初始化。

    (1)遇到 new、getstatic、putstatic或invokestatic 这四个关键字,如果类没有初始化,就需要先初始化。

        new:  使用new关键字

        getstatic和putstatic: 读取或设置一个静态字段(带final或已经在编译期把常量放到常量池的静态字段除外。)

        invokestatic: 调用一个类的静态方法

    (2)对类进行反射调用的时候,如果没有初始化,就先初始化。
    (3)初始化一个类,如果其父类没有初始化,就初始化父类。
    (4)虚拟机启动时,指定一个主类(main方法的类),会先初始化这个主类。
    (5)jdk1.7中, 如果一个 java.lang.invoke.MethodHandle实力最后的解析结果 REF_getstatic REF_putstatic REF_invokestatic的方法句柄,并且这个方法句柄所对应的类没有初始化,就先初始化。