JVM类加载器是Java虚拟机(JVM)的一部分,它负责将类的字节码加载到内存并转换为可执行的Java类。以下是关于JVM类加载器的详细解释:
一、类加载器的定义
类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。它会通过二进制流的方式获取到字节码文件的内容,然后将获取到的数据交给Java虚拟机。虚拟机会在方法区和堆上生成对应的对象保存字节码信息。
二、类加载器的作用
- 负责将.class文件(存储的物理文件)加载到内存中。
- 通过加载字节码数据放入内存转换成byte[],然后调用虚拟机底层方法将byte[]转换成方法区和堆中的数据。
- 确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全。
三、类加载器的分类
JVM中的类加载器主要分为以下几类:
启动类加载器(Bootstrap ClassLoader):
- 由JVM自身实现,通常使用C++编写,不是Java类。
- 负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class或Xbootclasspath选项指定的jar包。
- 它是所有类加载器的顶层类加载器,无法被Java程序直接引用。
扩展类加载器(Extension ClassLoader):
- 由Java实现,继承自ClassLoader类。
- 负责加载Java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar。
- 在JDK 9及之后的版本中,扩展类加载器被重命名为平台类加载器(Platform ClassLoader)。
应用程序类加载器(Application ClassLoader):
- 也称为系统类加载器(System ClassLoader)。
- 由Java实现,继承自ClassLoader类。
- 负责加载classpath中指定的jar包及-Djava.class.path所指定目录下的类和jar包。
自定义类加载器:
- 通过继承java.lang.ClassLoader类的方式实现。
- 可以根据应用程序的需求自定义类加载逻辑,如从网络下载类文件、解密等。
四、类加载的过程
类加载的过程包括以下几个步骤:
加载:将类的class文件读入到内存,并将这些静态数据转换成方法区中的运行时数据结构,同时在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。
连接:
- 验证:确保加载的类信息是否符合JVM规范,有没有安全方面的问题。
- 准备:为类中定义的变量(静态变量)分配内存并设置类变量默认初始值阶段,这些内存都在方法区中进行分配。
- 解析:虚拟机常量池的符号引用替换成直接引用的过程,也就是初始化变量的过程。
初始化:为类的静态变量赋予正确的初始值,并执行静态代码块。
五、双亲委派模型
双亲委派模型是Java类加载器的一个重要特性。当一个类加载器收到类加载请求时,它不会自己先去加载,而是把这个请求委托给父类加载器去执行。如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归。请求最终将到达顶层的启动类加载器。如果父类加载器可以完成类加载任务,就成功返回;如果父类加载器无法完成此加载任务,子加载器才会尝试自己去加载。
双亲委派模型的优点包括:
- 避免类的重复加载。
- 保证Java核心API不被篡改。
然而,双亲委派模型也有其局限性,如不能向下委派、不能不委派等。在某些情况下,可能需要打破双亲委派模型以满足特定需求。
综上所述,JVM类加载器是Java虚拟机的重要组成部分,它负责将类的字节码加载到内存并转换为可执行的Java类。通过了解类加载器的定义、作用、分类、加载过程以及双亲委派模型等知识点,可以更好地理解和使用Java技术。