当前位置: 首页 > article >正文

JVM类加载器(附面试题)

什么是类加载器

类加载器(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.kler.cn/a/507334.html

相关文章:

  • Spring Boot 实战篇(四):实现用户登录与注册功能
  • Git 版本控制:.gitignore 文件完全指南
  • tomcat文件目录讲解
  • Redis 3.2.1在Win10系统上的安装教程
  • opencv进行人脸识别环境搭建
  • 年后找工作需要注意的事项
  • Qt Quick 和 Qt Designer
  • 【设计模式-结构型】外观模式
  • 速通Docker === 常用命令
  • 【PCIe 总线及设备入门学习专栏 5.3.3 -- PCIe 掩图 mask 介绍】
  • 【鱼皮大佬API开放平台项目】Spring Cloud Gateway HTTPS 配置问题解决方案总结
  • SM3在线哈希运行
  • 【PPTist】幻灯片放映
  • Kubernetes 部署 RabbitMQ 集群教程
  • MATLAB 2025a更新了些什么?
  • sparkRDD教程之基本命令
  • 【设计模式-结构型】享元模式
  • ‌OCP英文全称是什么
  • ElementTree 库该怎么学习?
  • 华为EulerOS 学习,是否要先 RHCE?
  • Apache NiFi存在信息泄露漏洞(CVE-2024-56512)
  • Elasticsearch二次开发:实现实时定时同步同义词、近义词与停用词
  • Elasticsearch的function_score与rescore的区别
  • npm 方式安装Pyodide 详解
  • 小模型干大事情,基于LLaMA-Factory+Lora入门级微调开源AI模型
  • Windows远程桌面网关出现重大漏洞