、概述
首先先来看几个问题
jvm是如何加载这些Class文件的?
jvm加载一个Class文件需要哪些步骤?
Class文件中的信息进入到虚拟机后会发生什么变化?
接下来看看jvm加载class文件的概述:
jvm把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。这句话差不多已经回答上面三个问题的大部分了。
与那些在编译是需要进行连接工作的语言不同,在Java语言里面,类型的加载和连接过程都是在程序运行期间完成的,这样会在类加载是稍微增加一些性能开销,但是却能为Java应用程序提供高度的灵活性,Java中可以动态的扩展的语言特性就是依赖运行期动态加载和动态连接这个特点实现的。比如编写一个使用接口的应用程序,可以等到运行时在指定其实际的实现。这种组装应用程序的方式广泛应用于Java程序之中。
二、要点
类从被加载到jvm内存中开始,到卸载出内存为止,它的生命周期包括了一下步骤:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Useing)和卸载(Unloading)七个阶段。其中的验证、准备和解析三个部分统称为链接(Linking),这七个阶段的发生顺序如下图,注意是发生的顺序,不是执行完成的先后顺序。
1、加载
加载阶段是“类加载”过程的一个阶段,虚拟机需要做以下三件事:
通过一个类的全限定名来获取定义此类的二进制字节流。
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的入口。
加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,方法区中的数据存储格式有虚拟机实现自定义,虚拟机规范未规定此区域的具体数据结构。然后再Java堆中实例化一个java.lang.Class类的对象,这个对象作为程序访问方法区中的这些类型数据的外部接口。加载阶段与连接阶段的部分内容是交替进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。
2、验证
验证阶段虚拟机做了下面这些事情
1、文件格式验证
第一阶段是要验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。会验证一下这些内容。
主、次版本号是否在当前虚拟机处理范围之内。
常量池的常量中是否有不被支持的常量类型。
指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量。
CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据。
Class文件中各部分及文件本身是否有被删除的或附加的其他信息
2、元数