JVM类加载器(附面试题)

server/2025/1/20 23:14:10/

什么是类加载器

类加载器(ClassLoader) 是 Java 虚拟机(JVM)中的一个组件,用于在运行时将字节码文件加载到内存中,并将其转换为 JVM 可以执行的二进制数据结构。

字节码文件通常是以.class为扩展名的文件,这些文件包含了 Java 类的定义和相关的指令。

类加载器的功能

  1. 加载类: 将类的字节码文件(通常是 .class 文件)从文件系统或其他来源(如网络、JAR 包)加载到 JVM。
  2. 验证类: 确保加载的类符合 JVM 规范,避免加载损坏或不安全的字节码。
  3. 链接类: 将类的二进制数据与 JVM 关联,包括解析符号引用。
  4. 初始化类: 运行类的静态代码块和初始化静态变量。

类加载器的分类

启动类加载器(Bootstrap ClassLoader)

它是 Java 虚拟机内置的类加载器,由 C++ 语言编写,是 Java 类加载器层次结构中的顶层加载器。

主要负责加载 Java 核心类库,如java.lang包下的Object类、String类等最基础、最核心的 Java 类。 在 Java 代码中无法直接获取到启动类加载器的对象,它使用原生代码来加载类,加载路径是固定的,通常是 JVM 的内部路径。

扩展类加载器(Extension ClassLoader)

它的父加载器是启动类加载器,主要负责加载 Java 的扩展 API。

通常从 JRE/lib/ext 目录下加载类。例如,一些 Java 的扩展功能,像javax开头的部分扩展类库可能会由扩展类加载器加载。它可以被看作是对 Java 核心类库的补充,提供了一些额外的功能支持。

应用程序类加载器(Application ClassLoader)

也称为系统类加载器,它的父加载器是扩展类加载器。

负责加载用户类路径(classpath)下的类,是 Java 应用程序中默认的类加载器。一般情况下,我们编写的 Java 类都是由这个加载器加载。 例如,我们自己创建的项目中的 Java 类,包括main方法所在的类以及其他自定义的业务类等,大多是由应用程序类加载器加载。

自定义类加载器

可以通过继承ClassLoader类来创建自定义类加载器。

用于从特定的位置加载类或对类的加载过程进行特殊处理。例如,当需要从网络位置或者加密的文件中加载类时,可以使用自定义类加载器。自定义类加载器可以根据具体的业务需求灵活地加载类,比如在一些插件化开发的场景中,通过自定义类加载器来加载插件中的类,实现插件的动态加载和卸载。

双亲委派机制

双亲委派机制指的是:当一个类加载器接收到加载类的任务时,会自底向上查找是否加载过,再由顶向下进行加载。

在这里插入图片描述

举例1:

  • 应用程序类加载器接到了加载类A的任务,应用程序类加载器首先会检查自己加载过没有,没有加载过就交给父类加载器 - 扩展类加载器。
  • 扩展类加载器也没加载过,交给他的父类加载器 - 启动类加载器。
  • 启动类加载器发现已经加载过,直接返回。

举例2:

  • B类在扩展类加载器加载路径中,同样应用程序类加载器接到了加载任务,按照案例1中的方式一层一层向上查找,发现都没有加载过。
  • 那么启动类加载器会首先尝试加载。它发现这类不在它的加载目录中,向下传递给扩展类加载器。
  • 扩展类加载器发现这个类在它加载路径中,加载成功并返回。
  • 如果第二次再接收到加载任务,同样地向上查找。扩展类加载器发现已经加载过,就可以返回了。
双亲委派机制的作用

1.保证类加载的安全性。通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。

2.避免重复加载。双亲委派机制可以避免同一个类被多次加载。

面试

1、如果一个类重复出现在三个类加载器的加载位置,应该由谁来加载?

启动类加载器加载,根据双亲委派机制,它的优先级是最高的

2、String类能覆盖吗,在自己的项目中去创建一个java.lang.String类,会被加载吗?

不能,会返回启动类加载器加载在rt.jar包中的String类。

3、类的双亲委派机制是什么?

  • 当一个类加载器去加载某个类的时候,会自底向上查找是否加载过,如果加载过就直接返回,如果一直到最顶层的类加载器都没有加载,再由顶向下进行加载。
  • 应用程序类加载器的父类加载器是扩展类加载器,扩展类加载器的父类加载器是启动类加载器。
  • 双亲委派机制的好处有两点:第一是避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。第二是避免一个类重复地被加载。

4、打破双亲委派模型?

  • 当需要加载一些特殊的类或者实现一些特定的功能时会打破双亲委派模型。例如,在 Java 的 SPI(Service Provider Interface)机制中,当需要加载服务提供者的实现类时会打破双亲委派模型。
  • 以 JDBC 为例,Java 的DriverManager类在加载数据库驱动时,它会使用ServiceLoader机制。DriverManager类需要加载各个数据库厂商提供的Driver实现类,这些实现类并不在 Java 的核心类库范围内。为了能够加载这些类,DriverManager类会使用线程上下文类加载器(Thread Context ClassLoader)来加载这些实现类,而不是遵循双亲委派模型通过应用程序类加载器的父类加载器去加载。这样就打破了双亲委派模型,使得可以加载位于应用程序类路径下的特定服务实现类。

http://www.ppmy.cn/server/160011.html

相关文章

Tomcat下载配置

目录 Win下载安装 Mac下载安装配置 Win 下载 直接从官网下载https://tomcat.apache.org/download-10.cgi 在圈住的位置点击下载自己想要的版本 根据自己电脑下载64位或32位zip版本 安装 Tomcat是绿色版,直接解压到自己想放的位置即可 Mac 下载 官网 https://tomcat.ap…

神经网络常见面试题

梯度消失和梯度爆炸 1. 梯度消失(Vanishing Gradient) 定义: 梯度消失是指在反向传播过程中,梯度逐渐变得非常小,导致前面几层的权重更新非常缓慢,甚至几乎不更新,从而影响网络的学习过程。特…

Ubuntu更改apache的服务端口

1.介绍 承接上文,上文介绍了如何利用apache快速部署自己的网页,直接访问localhost就能打开网页的界面,这里其实是直接用了Ubuntu的80端口访问,如果我想换一个端口访问呢?应该怎么实现? 这一篇文章就来教你&…

第六章:PPP协议和HDLC协议配置与管理

目录 一、路由器概述 二、路由器的基本原理 1、路由器数据处理的过程: 2、度量值 3、影响路由度量值的因素 三、路由器基本配置 1、命令特点 2、常见命令模式 四、HDLC协议 五、PPP协议 六、PPP配置 1、任务 2、拓扑图 3、代码 4、测试 七、PAP认证配…

SC34018 免提手柄式扬声电话系统

SC34018合并了必需的放大器、衰减器和几种控制功能做成一种高品质的免提手柄式扬声电话系统。它包括一个话筒放大器、一个用于扬声器的音频功率放大器、发送和接收衰减器、背景噪声电平检测系统和一个衰减器控制系统,对发送和接收电平好于背景噪声做出反应。电路上还…

使用Redis防止重复发送RabbitMQ消息

问题 今天遇到一个问题,发送MQ消息的时候需要保证不会重复发送,注意不是可靠到达(可靠到达可以通过消息确认机制和回调接口保证),这里保证的是不会生产多条一样的消息。 方法 综合讨论下来决定使用Redis缓存来解决&…

游戏引擎学习第83天

回顾 昨天主要集中在实现位图缓存并优化使用。通过将位图缓存起来,避免了在屏幕上逐帧绘制所有内容的问题。具体来说,现在可以将任何需要绘制到屏幕上的内容直接绘制到位图中,类似于使用一系列的组合来生成地面纹理。由于目前的位图复制例程…

k8s pod 中通过service account 访问API Server

创建Role,Rolebinding, Service account 和Pod 创建Role apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: myns name: myrole rules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", …