JVM-类加载器

什么是类加载

我们写的java源文件先被编译成.class字节码文件,然后由类加载器加载到JVM内存中,加载完成以后就会得到一个Class对象,我们就可以使用new关键字来实例化这个对象。
在这里插入图片描述

加载过程

装载过程主要分为 加载、连接(验证、准备、解析)、初始化三个阶段
在这里插入图片描述
每个阶段的主要作用:
1、加载:查找和载入Class文件

2、链接,分为以下三个小阶段

  • 验证:验证载入的class文件数据的正确性
  • 准备:给类变量分配存储空间,并设置默认初始值0
  • 解析:将运行时常量池内的符号引用转换为直接引用的过程(符号引用是用一组符号描述所引用的目标;直接引用是指向目标的指针)

3、初始化:对静态变量,静态代码块执行初始化工作

学习了上面的知识之后,我们就可以解释为什么全局变量不用初始化而局部变量需要初始化了
类变量在链接的准备阶段会被默认赋值,然后在初始化阶段会被赋予实际的值
比如int a=1;
a在准备阶段=0,在初始化阶段=1

而局部变量表不存在系统初始化的过程,所以在使用前必须进行显式赋值

类加载器

类加载器就是负责进行类加载的装置

JVM在运行的时候,会产生3个类加载器,这三个类加载器组成了一个层级关系

每个类加载器分别去加载不同作用范围的jar包,比如

  • Bootstrap ClassLoader,主要是负责Java核心类库的加载,也就是 %{JDK_HOME}\lib下的rt.jar、resources.jar等

  • Extension ClassLoader,主要负责%{JDK_HOME}\lib\ext目录下的jar包和class文件

  • Application ClassLoader,主要负责当前应用里面的classpath下的所有jar包和类文件

除了系统自己提供的类加载器以外,还可以通过ClassLoader类实现自定义加载器,去满足一些特殊场景的需求。
在这里插入图片描述

为什么要自定义类加载器?

自定义加载逻辑
有时我们不一定是从类文件中读取类,可能是从网络的输入流中读取类,这就需要做一些加密和解密操作,这就需要自定义类加载器来实现加载类的逻辑。

隔离加载类
两个不同的应用程序可能会依赖同一个第三方类库的不同版本,为了保证两个版本的类都可以正常被加载,需要利用自定义类加载器加载不同版本的类,以此实现类的隔离加载

双亲委派机制

双亲委派机制

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

在这里插入图片描述

为什么要有双亲委派机制?

1、避免类的重复加载:
Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关系可以避免类的重复加载,当父加载器加载之后,子加载器就不会重复加载了、

2、防止核心API被随意篡改:
当自定义一个java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器发现该类已被加载,并不会重新加载自定义的java.lang.Integer,这样便可以防止核心API库被随意篡改。

那我非要自定义Integer类呢?
可以,但需要用自定义的类加载器去加载,因为系统的类加载器只加载jar包中的那个java.lang.Integer

打破双亲委派机制

如何打破呢?
只要我加载类的时候,不是从 Aapplication ClassLoader->Extension ClassLoader->BootStrap ClassLoader 这个顺序找,那就算是打破了
所以只要我自定义个ClassLoader,重写loadClass方法,方法中实现逻辑不依照往上开始寻找类加载器,那就算是打破双亲委派机制了。

有哪个场景破坏了双亲委派机制?——最典型的就是Tomcat
假设我现在有两个Web应用程序,它们都有一个类,叫做User,并且它们的类全限定名都一样,比如都是com.yyy.User。但是他们的具体实现是不一样的
那么Tomcat是如何保证它们是不会冲突的呢?
答案就是,Tomcat给每个 Web 应用自定义一个类加载器实例(WebAppClassLoader),该加载器重写了loadClass方法,优先加载当前应用目录下的类,如果当前找不到了,才一层一层往上找,这样就做到了Web应用层级的隔离

两个class对象相同的必要条件

在JVM中表示两个class对象是否为同一个类存在两个必要条件:

  • 类的完整类名必须一致。
  • 加载这个类的类加载器必须相同。

即:在JVM中,即使这两个类对象来源于同一个Class文件,被同一个虚拟机所加载,但只要加载它们的类加载器不同,那么这两个类对象也是不相等的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值