深入JVM:类加载器和双亲委派模型

article/2025/8/11 9:38:45

目录

  • 1. 什么是类加载器
  • 2. 类加载器的类型
  • 3. 双亲委派模型
  • 4. 类装载的过程
      • 加载
      • 验证
      • 准备
      • 解析
      • 初始化
      • 使用
      • 卸载

1. 什么是类加载器

如果想要了解什么是类加载器就需要清楚一个Java文件是如何运行的。我们可以看下图:

首先要知道操作系统是不能直接运行Java文件的,所以就需要通过JVM将Java文件转换为操作系统可以运行的文件类型,步骤如下:

  • 类加载器把Java代码转换为字节码文件
  • 运行时数据区将字节码文件加载到内存中,而字节码文件只是JVM的一套指令集规范,并不能直接交给底层操作系统来执行,而是需要有执行能力的执行引擎来运行
  • 执行引擎将字节码翻译为底层系统指令,再交给CPU来执行,而这个时候需要调用其它语言的本地库接口来实现整个程序的功能

JVM只会运行二进制文件,而类加载器(ClassLoader)的主要作用就是将字节码文件加载到JVM 中 ,从而让Java程序能够启动起来。现有的类加载器基本上都是 java.lang.ClassLoader的子类,该类的只要职责就是用于将指定的类找到或生成对应的字节码文件,同时类加载器还会负责加载程序所需要的资源

2. 类加载器的类型

类加载器根据各自的加载范围不同,进行了划分主要是四种:

  • 启动类加载器:这个类并不继承ClassLoader类,其中是由C++编写实现。用于加载JAVA_Home/jre/lib目录下的类库
  • 扩展类加载器:该列是ClassLoader的子类,主要是加载JAVA_HOME/jre/lib/ext目录中的类库
  • 应用类加载器:该类时ClassLoader的子类,主要是用于加载classPath下的类,也就是加载开发者自己编写的Java类
  • 自定义类加载器:开发者自定义类继承ClassLoader,实现自定义类加载规则

上述三种类加载器的层次结构如下如下:

而类加载器的体系不是继承关系的,而是委派体系,类加载器首先会到自己的父亲中查找类和资源,如果找不到才回到自己的本地进行查找。类加载器的委托行为动机是为了避免相同的类被多次加载

3. 双亲委派模型

如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类, 而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以 完成类加载任务,就返回成功;只有父类加载器无法完成此加载任务时,才由下一级去加载

那么为什么会需要使用双亲委派模型呢?

  • 通过双亲委派机制可以避免某一个类被重复加载,当父类已经加载后则无需重复加载,保证唯一性
  • 为了安全,保证类库API不会被修改

这里解释一下如何保证类库的API不会被修改:当我们创建一个类String的时候,由于在Java中本身就存在String类,所以使用双亲委派模型的时候,在启动类加载器就会加载Java中的String类,而不会使用应用类加载器进行加载。

public class String {public static void main(String[] args) {System.out.println("demo info")}
}

此时执行main函数,会出现异常,在类 java.lang.String 中找不到 main 方法

出现该信息是因为由双亲委派的机制,java.lang.String的在启动类加载器 (Bootstrap classLoader)得到加载,因为在核心jre库中有其相同名字的类文件, 但该类中并没有main方法。这样就能防止恶意篡改核心API库

4. 类装载的过程

类从加载到JVM中开始,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载七个阶段。其中,验证、准备和解析这三个部分统称为连接

加载

加载时主要的作用是以下三点:

  • 通过类的全名,获取类的二进制数据流
  • 解析类的二进制数据流为方法区内的数据结构(Java类模型)
  • 创建java.lang.Class类的实例,表示该类型。作为方法区这个类的各种数据的访问入口

上面说的可能优点难以理解,以这个图片来讲解一下它的作用。就比如当前有一个Person进行类的加载,那么他主要是分为两个部分,第一部分将Person中定义的字段以及方法存储到元空间中,第二部分时将实例化的对象存储到堆中,而堆当中的实例化对象的对象头会指向当前的class对象,然后class对象指向元空间的数据结构

验证

验证类是否符合 JVM 规范,安全性检查

  • 文件格式验证:是否符合Class文件的规范
  • 元数据验证
    • 这个类是否有父类(除了Object这个类之外,其余的类都应该有父类)
    • 这个类是否继承(extends)了被final修饰过的类(被final修饰过的类表示类不能被继承)
    • 类中的字段、方法是否与父类产生矛盾。(被final修饰过的方法或字段是不能覆盖的)
  • 字节码验证
    • 主要的目的是通过对数据流和控制流的分析,确定程序语义是合法的、符合逻 辑的
  • 符号引用验证:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量

准备

为类变量分配内存并设置类变量初始值

  • static变量,分配空间在准备阶段完成(设置默认值),赋值在初始化阶段完成
  • static变量是final的基本类型,以及字符串常量,值已确定,赋值在准备阶段完成
  • static变量是final的引用类型,那么赋值也会在初始化阶段完成
public class Application {static int b = 10;static final int c= 20,static final String d = "hello";static final Object obj= new Object();
}

解析

把类中的符号引用转换为直接引用

比如:方法中调用了其他方法,方法名可以理解为符号引用,而直接引用就是使用指针直接指向方法

初始化

对类的静态变量,静态代码块执行初始化操作

  • 如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类
  • 如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行

使用

JVM 开始从入口方法开始执行用户的程序代码

  • 调用静态类成员信息(比如:静态字段、静态方法)
  • 使用new关键字为其创建对象实例

卸载

当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存


http://www.hkcw.cn/article/wergQNosQO.shtml

相关文章

【JVM —— 03 类的生命周期】

Java 类的生命周期指的是一个类从加载到内存到卸载出内存的整个过程。这一过程主要包括以下几个阶段: 加载(Loading)连接(Linking) 验证(Verification)准备(Preparation)…

Arthas简介及示例

一、什么是Arthas? Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方…

JVM考古现场(十七):鸿蒙初辟——从太极二进到混沌原初的编译天道

"此刻正是奇点编译的第3.1415926秒!伏羲的算筹正在撕裂冯诺依曼架构的次元壁!诸君请看——这JVM堆内存中正在孕育盘古的元神!" 目录(终极扩展) 第一章:太极二进——内存模型的阴阳交缠 第二章&a…

JVM的组成

JVM 运行在操作系统之上 java二进制字节码文件的运行环境 JVM的组成部分 java代码在编写完成后编译成字节码文件通过类加载器 来到运行数据区,主要作用是加载字节码到内存 包含 方法区/元空间 堆 程序计数器,虚拟机栈,本地方法栈等等 随后来到执行引擎,主要作用是翻译字…

【java面试题】二进制(详解,一看就会)

二进制 1.什么是二进制 二进制是一种数值表示系统,它使用两个符号表示数字:0和1。它是计算机系统的基础,因为计算机使用二进制数来进行数据存储和处理。在二进制中,每一位代表一个2的幂次方,比如: 0 020…

Java 2.4 - JVM

一、Java 内存区域详解(重点) 本篇讨论的是 HotSpot 虚拟机 相比于 C 而言,程序员不需要对每个 new 操作都写对应的 delete / free 操作,这些操作我们会交给虚拟机去做。因此,如果不了解虚拟机的原理,一旦…

java面试-- 必问之jvm与性能优化(一)

问题一、 描述一下 JVM 加载 Class 文件的原理机制? JVM(Java虚拟机)加载Class文件的原理机制是Java程序运行的关键组成部分。这一过程涉及到多个阶段,确保Java程序能够跨平台运行,并动态地加载、解析和执行Java Class文件。以下…

JVM运行时数据区之虚拟机栈

【1】概述 Java虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用。 栈是运行…

【Linux探索学习】第三十二弹——生产消费模型:基于阻塞队列和基于环形队列的两种主要的实现方法

Linux学习笔记: https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言: 在前面我们已经学习了关于线程的主要知识,包括线程的基础知识以及线程的同步与互斥等内容,今天我们来学几个线程知…

复现FAST_LIVO2【Ubuntu 20.04.6 LTS】

目录 准备1 Ubuntu 和 ROS2 其他库2.1 PCL2.2 Eigen2.3 OpenCV 3 Sophus3.1 安装3.2 make报错 4 Vikit5 livox_ros_driver5.1 Livox-SDK5.2 livox_ros_driver FAST-LIVO2运行参考 准备 1 Ubuntu 和 ROS 依据开源介绍,Ubuntu 16.04~20.04。 复现版本为:…

【基于Ubuntu下Yolov5的目标识别】保姆级教程 | 虚拟机安装 - Ubuntu安装 - 环境配置(Anaconda/Pytorch/Vscode/Yolov5) |全过程图文by.Akaxi

目录 一.【YOLOV5算法原理】 1.输入端 2.Backbone 3.Neck 4.输出端 二.【系统环境】 1.虚拟机的安装与创建 2.安装Ubuntu操作系统 3.环境的配置 3.1.Ubuntu下Anacoda安装以及虚拟环境配置 3.2.Pytorch安装 3.3.Vscode安装 3.4.Yolov5源码及环境获取安装…

[已解决] 本地两台 win电脑 (以太网) 网线传输文件 - 局域网连接 (解决windows无法访问共享文件问题 - Windows 安全中心输入网络凭据 用户名/密码 不正确问题)

背景 由于要本地传输的数据比较大,大几百GB网盘传输慢,正好有网线,试着本地网线高速传输(实测113MB/s)踩了很多坑,想把亲测成功的经验分享出来帮助更多同学 目录 1 网线接入 2 设置两台电脑的IP地址 3 …

Docker(三):DockerFile

一、DockerFile介绍 1、DockerFile 介绍 DockerFile 是一种能够被Docker 程序解释的文件(一般为了方便理解称之为“剧本”)。 DockerFile 由一条一条的指令组成,并且有自己的书写格式和支持的命令。当我们需要在容器 镜像中指定自己额外的需…

【Linux网络编程】第十弹---打造初级网络计算器:从协议设计到服务实现

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【Linux网络编程】 目录 1、Protocol.hpp 1.1、Request类 1.1.1、基本结构 1.1.2、构造析构函数 1.1.3、序列化函数 1.1.4、反…

Ubuntu24安装Docker详细教程

目录 Ubuntu 安装 Docker 详细教程 一、安装环境说明 二、卸载旧版 Docker(若存在) 三、安装必要的依赖 四、添加 Docker 的 GPG 密钥 五、配置 Docker 的软件源 六、安装 Docker docker-compose离线安装 七、验证 Docker 是否安装成功 八、配置…

2024第八届御网杯信息安全网络大赛线上WP详解(misc+cryoto)(详解-思路-脚本)

芜湖~ 首届御网杯线上和ISCC分开进行 但还是用的ISCC的页面差评 嘻嘻 又是玄乎的一天 以下是我自己的一些思路和解析 有什么问题或者建议随时都可以联系我 目录 附件 # Misc ##Notice ##编码转换 Brainfuck编码 jsfuck编码 Ook! 编码 ##bluetooth 导出压缩包 第一…

在Linux中安装、配置和挂载NFS的完整指南

一、NFS简介 NFS(Network File System) 是一种分布式文件系统协议,允许用户通过网络在不同主机间共享文件和目录。它适用于局域网环境,常用于服务器集群、数据共享等场景。本文详细介绍NFS服务端与客户端的安装、配置及挂载流程。…

Linux-Ubuntu下的git安装与配置

一、安装git 1.打开终端,运行以下命令(需要联网) sudo apt-get update sudo apt-get install git 2.验证安装 安装完成之后,通过运行以下命令验证git是否已经正确安装: git --version 二、配置git 2.1.配置用户名…

亲测可用:wsl2安装ubuntu22.04的GNOME桌面

本文主要介绍wsl安装的ubuntu如何配置图形化桌面,主要使用与windows操作系统环境,方便搭建Linux环境下的可视化开发环境,网上流传的很多教程都不能正确安装,以下是本人亲自验证可用的操作方法。 1、开始安装 1.1 配置源 sudo v…

个人健康中枢的多元化AI网络革新与精准健康路径探析

引言 随着数字化转型的深入推进,个人健康中枢作为集成化健康管理系统,正在从传统的单一功能向多元化的AI驱动方向快速发展。在这一背景下,新兴网络硬件技术,特别是DPU(数据处理单元)和全光网络的出现,为个人健康中枢的革新提供了前所未有的机遇。本研究将深入探讨这些技…