首页 > 代码库 > 深入理解Java虚拟机-----------虚拟机类加载机制

深入理解Java虚拟机-----------虚拟机类加载机制

虚拟机类加载机制

  类从被加载到虚拟机内存开始,到卸载出内存为止,整个生命周期包括:加载,验证,准备,解析,初始化,使用,卸载等7个阶段。其中,验证,准备,解析3个部分称为连接。

  以上7个阶段中,加载,验证,准备,初始化和卸载五个阶段的顺序是确定的,类的加载过程必需按照这种顺序按部就班的开始(开始并不意味着按部就班的“进行”或“完成”,因为这些阶段通常是互相交叉地混合式进行的)而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定。

  类的加载过程地第一阶段地开始是未曾决定地,虚拟机可以根据具体情况来自由把握。而对于初始化这个阶段,虚拟机规范则严格规定了只有5种情况必须立即对类进行:

  1. 遇到new,getstatic,putstatic或invokestatic这4条字节码时,若未进行初始化,则马上进行初始化;

  2. 使用java.lang.reflect包地方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。

  3. 当初始化一个类地时候,如果发现其父类还未进行初始化,则先初始化其父类;

  4. 当虚拟机启动的时候,用户需要指定一个要执行地主类,虚拟机会先初始化这个主类;

  5. 当使用JDK 1.7地语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,因此需要对其立刻进行初始化。

  有且只有这五种情况,会进行主动触发初始化(主动引用),否则,则不进行初始化(被动引用)。

  接口的加载过程与类加载过程稍微有点不同之处,针对接口需要做一些特殊说明:接口也有初始化过程,这一点与类是一致的,类中的语句大多是用静态语句块“static{}”来输出初始化信息的,而接口种不能使用“static{}”语句块,但编译器仍然会为接口生成“<clinit()>”类构造器,用于初始化接口种所定义的成员变量。接口和类的初始化不同在于第三点,接口在初始化的过程种,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的时候材化进行初始化。

  类加载的过程

  1. “加载” 是 “类加载”过程的一个阶段,在加载阶段,虚拟机需要完成以下3种事情:

  1) 通过一个类的全限定名来获取定义此类的二进制流。

  2) 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

  3) 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。 

 

深入理解Java虚拟机-----------虚拟机类加载机制