JVM类加载器

本文详细介绍了Java虚拟机(JVM)中的类加载机制,包括类加载器的层次结构、类加载过程、显示与隐式加载的区别、双亲委派机制及其优点,并探讨了类描述对象的唯一性以及破坏双亲委派机制的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java编程中除了基本数据类型,绝大多数都是使用引用类型变量,也就是我们常说的对象,基本数据类型也可以自动装箱为对应的引用类型变量,所以Java编程中一切皆为对象,JVM本身提供基本类库JFC,开发者可以自己设计类库,也可引用第三方类库,JVM是如何使用这些类文件的是我们本节研究的课题。在此抛出几个结论,然后使用Java代码验证这些结论的正确性,对不确定的功能给出一些推测,大家可以参考官方文档继续学习讨论。
一、JVM类加载器是一个层次树状结构,官方提供三级类加载器,用户在四级上继续扩展到任意层级。像我们常用的Tomcat至少扩展了三级类加载器({TOMCAT_HOME}/lib,WEB-INF/lib,WEB-INF/classes);再如OSGi框架其余类加载器实现JAVA代码的热部署
这里写图片描述

二、JVM类加载过程

这里写图片描述

A)加载:通过类的全路径名称,查询到Class类文件,读取文件字节流到JVM永久区生成类对应的描述对象java.lang.Class
B)验证:目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求。主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。例如Java8编译器编译的类无法在Java7上验证通过。
C)准备:为类静态变量(即static修饰的字段变量)分配内存并且设置该类变量的初始值即0,不包括final修饰的static变量,此类变量在编译时已经分配地址。
D)解析:主要将常量池中的符号引用替换为直接引用的过程。符号引用就是一组符号来描述目标,可以是任何字面量,而直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄
E)初始化:类加载最后阶段,若该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化成员变量(如前面只初始化了默认值的static变量将会在这个阶段赋值,成员变量也将被初始化)

三、编写代码如何触发类加载
显示类加载:
在代码中通过调用ClassLoader加载class对象,如直接使用Class.forName(name)或this.getClass().getClassLoader().loadClass()加载class对象
隐式类加载:
不直接在代码中调用ClassLoader的方法加载class对象,而是通过虚拟机自动加载到内存中,如在加载某个类的class文件时,该类的class文件中引用了另外一个类的对象,此时额外引用的类将通过JVM自动加载到内存中。

四、类加载的双亲委派及好处
双亲委派模式是在Java 1.2后引入的,其工作原理的是,如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。

五、类描述对象(java.lang.Class)如何确定唯一性,同一个类是否可以被同一虚拟机加载多次。
类的描述对象java.lang.Class需与其类加载器对象确定唯一性,也就是说类A与类A对应的类加载器LoaderA唯一确定类A的java.lang.Class对象ClassA,如果类A同时由被类加载器LoaderB加载生成的对象java.lang.Class对象ClassB,ClassA与ClassB是不同的,它们都在内存的永久区,虽然它们都是使用相同的类文件A.class生成,ClassB的对象与ClassA的对象不可以相互转化。

六、双亲委派的破坏者线程上下文类加载器ContextClassLoader。
为什么需要破坏类加载器的双亲委派机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值