JVM类加载机制原理及用法解析
JVM类加载机制是Java虚拟机的一个核心机制,它负责将Java类从.class文件加载到内存中,并对其进行链接、初始化等操作。在Java中,类加载机制是一个非常重要的机制,它直接关系到Java程序的正确执行。
类加载机制可以分为五个部分:加载、验证、准备、解析和初始化。
加载是类加载过程中的第一个阶段,这个阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的入口。注意这里不一定非得要从一个Class文件获取,这里既可以从ZIP包中读取(比如从jar包和war包中读取),也可以在运行时计算生成(动态代理),也可以由其他文件生成(比如将JSP文件转换成对应的Class类)。
验证是为了确保Class文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间。注意这里所说的初始值概念,比如一个类变量定义为:public static int v = 8080; 实际上变量v在准备阶段过后的初始值为0而不是8080,将v赋值为8080的put static指令是程序被编译后,存放于类构造器<client>方法之中。
解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是class文件中的:1. CONSTANT_Class_info 2. CONSTANT_Field_info 3. CONSTANT_Method_info等类型的常量。符号引用:符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。
初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载器以外,其它操作都由JVM主导。到了初始阶段,才开始真正执行类中定义的Java程序代码。初始化阶段是执行类构造器<client>方法的过程。<client>方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。
类加载器是JVM中的一种机制,它负责加载类到内存中。JVM中有三种类加载器:启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader)。
启动类加载器负责加载JAVA_HOME\lib目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt.jar)的类。
扩展类加载器负责加载JAVA_HOME\lib\ext目录中的,或通过java.ext.dirs系统变量指定路径中的类库。
应用程序类加载器负责加载用户路径(classpath)上的类库。
JVM通过双亲委派模型进行类的加载,当然我们也可以通过继承java.lang.ClassLoader实现自定义的类加载器。
双亲委派模型是指类加载器的加载机制,它可以确保类的加载顺序是正确的。在加载类时,JVM会首先使用启动类加载器加载类,如果启动类加载器无法加载类,则使用扩展类加载器加载类,如果扩展类加载器也无法加载类,则使用应用程序类加载器加载类。这种机制可以确保类的加载顺序是正确的,并且可以避免类的重复加载。