Java虚拟机类加载机制

一、类加载过程

Java虚拟机类加载机制

1、加载:通过一个类的全限定名来获取定义此类的二进制字节流;将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
2、验证:确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机的自身安全。
        文件格式验证(字节流是否符合Class文件格式规范,例如:是否以魔数0xCAFEBABE开头、主次版本号是否在当前虚拟机处理范围、常量池中的常量是否有不被支持的常量类型、常量指向的各种索引值是否有尚不存在的常量和不符合类型的常量、CONSTANT_ Utf8_ info型的常量中是否有不符合UTF8 编码的数据等等)
        元数据验证(对字节码描述的类信息进行语义分析,保证其描述信息符合java语言规范要求,例如:这个类是否有父类、这个类是否继承了不允许被继承的类(final)、类中的字段与方法是否与父类产生的矛盾等等)
        字节码验证(通过数据流和控制流分析,确定语义是合法的、符合逻辑的。例如:保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作、保证跳转指令不会跳到方法体以外的字节码指令上、保证方法体中类型转换是有效的等等)
        符号引用验证(发生在虚拟机将符号引用转换为直接引用时,这个转化动作在【解析】阶段发生。例如:符号引用中通过字符串描述的全限定名是否能找到对应的类、符号引用中类、字段、方法的访问性(public private protected default)是否可被当前类访问)
3、准备:正式为类变量分配内存并设置类变量初始值,进行内存分配的仅包括静态变量,设置变量初始值是变量的零值,代码中设置的值会在【初始化】阶段进行赋值操作,如果静态变量被final修饰,则【准备】阶段设置的初始值就是代码中设置的值。
4、解析:虚拟机将常量池中的符号引用转换为直接引用的过程。符号引用和直接引用。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符。
5、初始化:真正开始执行类中定义的java程序代码(或字节码),执行类构造器<clinit>()方法的过程。

二、类加载器

Java虚拟机类加载机制

1、启动类加载器:负责将存放在JAVA_HOME\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库(文件名识别,如rt.jar,名称不符合的即使放在lib目录下也不会被加载)加载到虚拟机内存中。无法被java程序直接使用。
2、扩展类加载器:负责加载JAVA_HOEM\lib\ext目录下,或者被java.ext.dirs系统变量所指定的路径中的所有类库。开发者可以直接使用。
3、应用程序类加载器:这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,也称为系统类加载器,负责加载用户类路径(CLassPath)上所制定的类库。开发者可直接使用。如果没有自定义类加载器,一般情况下这个就是程序中的默认类加载器。

说明:类加载器的这种层次关系,称为类加载器的双亲委派模型。除了顶层类加载器外,其余类加载器都应当有自己的父类加载器。类加载器的父子关系一般不会以继承关系来实现,而是都使用组合关系来复用类加载器代码。

Java虚拟机类加载机制