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

【JVM】类加载机制及双亲委派模型

目录

一、类加载过程

1. 加载

2. 连接

a. 验证

b. 准备

c. 解析

3. 初始化

二、双亲委派模型 

类加载器 

双亲委派模型的工作过程

双亲委派模型的优点


一、类加载过程

JVM的类加载机制是JVM在运行时,将 .class 文件加载到内存中并转换为Java类的过程。它是Java语言实现跨平台特性的核心之一。

对于一个类来说,它的生命周期是这样的:

其中,类加载的过程主要可以分成 5 个步骤(前 5 步),中间 3 步都属于连接,所以也可以说类加载过程主要分成 3 个步骤:

1. 加载

2. 连接

  • 验证
  • 准备
  • 解析

3. 初始化

下面我们来看每个步骤的具体执行内容:

1. 加载

“加载”阶段是整个“类加载”过程中的一个阶段,它和类加载是不同的。

加载阶段是指将类的字节码文件加载到内存中的过程。在加载 Loading 阶段,Java虚拟机需要完成以下三件事情:

1)通过一个类的全限定名来获取定义此类的二进制字节流。(全限定名,例如:java.lang.String)

2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3)在内存中生成一个代表这个类的 .class 对象,作为方法区这个类的各种数据的访问入口。

2. 连接

a. 验证

确保加载的类符合JVM规范和Java语言规范,即确保读到的 .class 文件(字节码文件),是合法的格式。

文件格式如下图所示,此处就不详细介绍了。

b. 准备

给类的静态变量分配内存空间,并设置类变量的默认初始值。

比如此时有这样一行代码:

public static int value = 123;

它是初始化 value 的值为0(默认值),而非 123。

c. 解析

解析阶段是 JVM 将类、接口、字段和方法(运行时常量池)的符号引用解析为直接引用。

  • 符号引用的获取: 在加载阶段和连接阶段之前,Java虚拟机会将类、接口、字段和方法的符号引用存储在运行时常量池中。解析阶段首先要做的就是从运行时常量池中获取符号引用。

  • 符号引用的匹配: 获取到符号引用后,解析阶段会尝试将这些符号引用匹配到目标对象(类、接口、字段或方法)的直接引用。匹配的过程包括查找目标对象在内存中的位置以及确定访问权限等。

  • 直接引用的生成: 一旦符号引用成功匹配到目标对象,解析阶段就会生成对应的直接引用。直接引用是指直接指向内存中目标对象的指针或偏移量,它能够直接在程序中被使用。

  • 解析结果的存储: 解析阶段最终会将生成的直接引用存储在运行时常量池中,以便后续的使用。

3. 初始化

初始化阶段是类加载过程的最后一个阶段,主要负责执行类变量的赋值操作和静态代码块的初始化。

  • 执行类变量的赋值操作,即按照程序员在代码中指定的初始值为静态变量赋值。这些值可以是程序中直接赋予的值,也可以是静态代码块中的计算结果。
  • 如果类中存在静态代码块,则会按照在代码中的顺序执行静态代码块中的内容。静态代码块中可以包含任意合法的 Java 代码,用于执行一些静态初始化操作。

上述的一系列类加载过程,可以简单概况为以下内容:

  1. 加载(Loading): 加载阶段是指将类的字节码文件加载到内存中的过程。当程序中使用到某个类时,JVM会通过类的全限定名(Fully Qualified Name)来加载类。类加载器会根据类的全限定名在文件系统或网络中查找相应的.class文件,并将其加载到内存中。

  2. 连接(Linking): 连接阶段包括验证、准备和解析三个步骤:

    • 验证(Verification): 确保加载的类符合JVM规范和Java语言规范,以防止恶意代码的注入。
    • 准备(Preparation): 为类的静态变量分配内存空间,并设置默认初始值。
    • 解析(Resolution): 将类、接口、字段和方法的符号引用解析为直接引用,以便后续执行。
  3. 初始化(Initialization): 初始化阶段是类加载过程的最后一个阶段,它负责执行类构造器的<clinit>方法,即对类的静态变量进行赋值操作和执行静态代码块。

二、双亲委派模型 

提到类加载机制,就不得不提“双亲委派模型”。它是 Java 类加载机制中的一种设计思想,JVM的类加载机制采用的就是双亲委派模型。

类加载器 

在 JVM 中,有一个重要的组件称为“类加载器”,它负责加载 Java 类文件到 JVM 中(根据类的全限定名来查找并加载对应的类文件,例如:java.lang.String)。JVM 中的类加载器默认有以下三种:

  1. 启动类加载器(Bootstrap Class Loader): 它是 JVM 的内置类加载器,负责加载 Java 核心类库(rt.jar)等核心类文件(标准库),是整个类加载器层次结构的顶层。由于它是用本地代码实现的,所以在 Java 中无法直接获取对其的引用。

  2. 扩展类加载器(Extension Class Loader): 它是用来加载 Java 平台的扩展库(ext 目录下的jar包)的类加载器。它的父类加载器是启动类加载器。通常情况下,我们可以通过 ClassLoader.getSystemClassLoader().getParent() 获取到扩展类加载器的引用。

  3. 应用程序类加载器(Application Class Loader): 也称为系统类加载器,它是用来加载应用程序的类文件的类加载器,它负责加载类路径(classpath)上指定的类库。它的父类加载器是扩展类加载器。通常情况下,我们可以通过 ClassLoader.getSystemClassLoader() 获取到应用程序类加载器的引用。 

除了上述的三种主要的类加载器之外,JVM 还支持用户自定义的类加载器,用户可以根据需要实现自己的类加载器来加载特定的类文件。用户自定义的类加载器通常继承自  java.lang.ClassLoader 类,并重写其 findClass() 方法来实现类加载的逻辑。

双亲委派模型的工作过程

双亲委派模型的工作过程如下: 

  • 当一个类加载器收到类加载请求时,它不会立即尝试自己去加载这个类,而是先将这个请求委派给它的父类加载器去完成。这个过程会一直向上进行,直到达到最顶层的启动类加载器。只有当父类加载器反馈自己无法完成这个加载请求(即在其搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载这个类。

双亲委派模型的优点

上述设定有以下几个优点:

  1. 安全性: 双亲委派模型可以帮助保证 Java 类库的安全性。由于类加载器会先委托给父类加载器加载类,这样可以防止恶意类被加载到 JVM 中。父类加载器通常是由 JVM 提供的,是由Java官方实现,因此可以信任。这有助于防止在 Java 应用程序中意外加载不安全或有潜在安全风险的类。例如,我们在代码中自己定义了一个 java.lang.String 这样的类,根据双亲委派模型的设定,这个类会被启动类加载器找到并加载,此时加载的是Java核心类,而自定义的 java.lang.String 类实际上是不会被加载的,这就保证了Java核心类库中的类无法被替换。

  2. 避免重复加载类: 双亲委派模型可以避免同一个类被多次加载到 JVM 中。当一个类被加载后,它会被缓存起来,以避免重复加载。这有助于节省内存空间,并且可以确保所有代码都是基于相同的类实例运行。

  3. 统一性: 双亲委派模型可以确保 Java 类库的一致性。因为所有的类加载请求都会经过父类加载器,所以无论是在 Java 应用程序中还是在 Java 核心类库中,都可以保证加载的是同一个类。

双亲委派模型在生活中的类比:

  • 假设你在一家公司工作,你的经理接到了一个任务,他会根据任务的性质和自己的能力来判断是否能够完成这个任务。
  • 如果经理认为自己无法完成任务,他会将任务转交给更高级别的领导,如部门主管或总经理。
  • 只有当更高级别的领导无法完成任务时,任务才会逐级向下转交,直到有可能被转交给你。这种机制确保了任务能够被最适合的人完成,提高了工作效率和质量。

双亲委派模型,是Java虚拟机(JVM)遵循的默认类加载机制。但也有一些方式能够打破这个机制,这里简单介绍:

  • 自定义类加载器: 开发自定义类加载器可以完全改变类加载的方式。通过实现自定义的ClassLoader类,可以实现不同于双亲委派模型的加载行为。例如,可以实现一个不遵循双亲委派模型的类加载器,直接从指定的位置加载类,而不是按照双亲委派模型从上至下逐级加载。

相关文章:

【JVM】类加载机制及双亲委派模型

目录 一、类加载过程 1. 加载 2. 连接 a. 验证 b. 准备 c. 解析 3. 初始化 二、双亲委派模型 类加载器 双亲委派模型的工作过程 双亲委派模型的优点 一、类加载过程 JVM的类加载机制是JVM在运行时&#xff0c;将 .class 文件加载到内存中并转换为Java类的过程。它…...

WordPress插件:链接自动识别转为超链接

WordPress插件&#xff1a;链接自动识别转为超链接 <?phpfunction open_links_in_new_tab() {add_filter(the_content, make_clickable);function autoblank($text) {$return str_replace(<a, <a target"_blank", $text);return $return;}add_filter(th…...

Java----数组的定义和使用

1.数组的定义 在Java中&#xff0c;数组是一种相同数据类型的集合。数组在内存中是一段连续的空间。 2.数组的创建和初始化 2.1数组的创建 在Java中&#xff0c;数组创建的形式与C语言又所不同。 Java中数组创建的形式 T[] 数组名 new T[N]; 1.T表示数组存放的数据类型…...

【C++】-QT多线程-006

1【QT】多线程 #ifndef MYWIDGET_H #define MYWIDGET_H#include <QWidget>namespace Ui { class MyWidget; }class MyWidget : public QWidget {Q_OBJECTpublic:explicit MyWidget(QWidget *parent 0);~MyWidget();/* 5 自定义信号*/ /*所有的信号函数只声明不定义&…...

vscode go语言开发中在任意包运行和调试代码 Example使用方法

一般情况下我们在进行go语言开发的时候我们都需要创建一个main方法和main包才能运行go代码&#xff0c; 针对这个问题&#xff0c;go语言给我们内置了功能强大的testing测试框架&#xff0c; 其中一个很有意思的Example测试就非常的方便使用。 他不管你在什么包&#xff0c;也…...

数据库查询--条件查询

目录 1.关系运算条件的查询 2.逻辑运算符条件的查询 3.带关键字IN的查询 4.带BETWEEN AND关键字的查询 5.空值查询 6.带LIKE关键字的模糊查询 1.关系运算条件的查询 在SELECT语句中&#xff0c;最常见的是使用WHERE字句指定关系运算条件对数据进行过滤。 语法格式&#x…...

用 Python 和 AkShare 进行个股数据清洗:源码剖析和建议优化

这是《个股清洗源码》一个获取股票买卖盘信息并将其打印到控制台并保存到文件的脚本。 下面我们来对源码进行剖析 先复习一下源码 import os import akshare as ak from akshare import stock_bid_ask_em from datetime import datetime import pandas as pd from io import …...

颍川诞生了两个帝王的仲父

伯、仲、叔、季是古代兄弟的长幼排行顺序&#xff0c;《释名释亲属》载&#xff1a;“父之弟曰仲父……仲父之弟曰叔父”。也就是古代称父亲的兄弟为仲父&#xff0c;多用于帝王对宰相重臣的尊称。 历史上最有名的、有正史记载的帝王“仲父”有两位&#xff0c;而且都出自颍川…...

SpringAMQP发布、订阅——Fanout Exchange交换机代码模拟

发布订阅模型: MQ提供了很多交换机模型 其中常用的有下边三个: Fanout:广播 Direct:路由 Topic:话题 转换器只负责消息路由&#xff0c;不是存储&#xff0c;路由失败则消息丢失 Fanout Exchange:会将接收到的消息路由导每一个跟其绑定的queue. 利用SpringAMQP演示Fanout…...

js原生三种弹框

第一种&#xff1a; alert("提示内容")&#xff1a;提示弹框&#xff1b; alert("提示"); 第二种&#xff1a; prompt("内容","输入框默认值")&#xff1a;输入弹框&#xff0c;第一个值输入框提示内容&#xff0c;第二个值输入框默…...

LWIP+TCP客户端

一、TCP API函数 其中tcp_poll()函数的第三个参数表示隔几秒调用一次这个周期性函数 二、修改服务器的IP 三、TCP客户端编程思路 申请套接字绑定服务器IP和端口号等待客户端连接 进入连接回调函数在连接回调函数中 配置一些回调函数&#xff0c;如接收回调函数&#xff0c;周期…...

程序人生 | 人生如棋,落子无悔

人生的开始&#xff0c;始于哭声&#xff0c;浮浮沉沉几十年。终了&#xff0c;一声长叹&#xff0c;在一片哭声中撒手离去。 人生的道路虽然漫长&#xff0c;但是关键就是那么几次机会的选择&#xff0c;可以决定此后几十年的光阴。 有个故事讲&#xff1a;古代有个人去砍柴…...

python的deap库使用记录

主要是在遗传符号回归的代码中添加了注释和根据一部分源码做了一点改动 import operator import random import numpy as np import matplotlib.pyplot as plt from deap import algorithms, base, creator, tools, gp from operator import attrgetter##生成数据 def generat…...

一份简历的制作

个人简历是求职者面试前最需要准备的一项工具。一份好的简历可以帮助求职者获得更多的面试机会&#xff0c;并且为面试时的表现奠定基础。以下介绍制作简历的几个注意点&#xff0c;仅供参考。 一、个人信息 姓名*性别联系方式 &#xff08;手机号&#xff09;电子邮箱&#…...

网络匿名--不只是TOR

今天&#xff0c;我们将讨论互联网匿名和隐私&#xff1a; 如何隐藏你的真实身份。 什么是 TOR 。 如何以完全匿名的方式执行黑客任务。 如何使用proxy chain。 如何让我们的匿名性领先一步。 如何使用特定的操作系统保持匿名。 结论&#xff0c;如何实现互联网匿名和隐…...

【论文阅读笔记】Order Matters(AAAI 20)

个人博客地址 注&#xff1a;部分内容参考自GPT生成的内容 论文笔记&#xff1a;Order Matters&#xff08;AAAI 20&#xff09; 用于二进制代码相似性检测的语义感知神经网络 论文:《Order Matters: Semantic-Aware Neural Networks for Binary Code Similarity Detection》…...

中科院突破:TalkingGaussian技术实现3D人脸动态无失真,高效同步嘴唇运动!

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; 引言&#xff1a;探索高质量3D对话头像的新方法 在数字媒体和虚拟互动领域&#xff0c;高质量的3D对话头像技术正变得日益重要。这种技术能够在虚拟现实、电影…...

fastText-文本分类

fastText介绍 fastText是一个快速文本分类算法,与基于神经网络的分类算法相比有两大优点: 1、fastText在保持高精度的情况下加快了训练速度和测试速度 2、fastText不需要预训练好的词向量,fastText会自己训练词向量 3、fastText两个重要的优化:Hierarchical Softmax、N-gr…...

【nodejs 命令行交互神器 - inquirer.js】

需求 大家在开发时&#xff0c;有时需要从命令行读取用户的输入&#xff0c;或者让用户选择。在nodejs中&#xff0c;这个怎么实现? 原生实现 ❌ process.stdin.setEncoding(utf8);process.stdin.on(readable, () > {let chunk;// 使用循环确保我们读取所有的可用输入wh…...

Liunx软件包管理(上)

目录 一.前言 二.rpm RPM 包的结构 安装与升级 卸载 查询 验证 信息输出 三.yum Yum 的特点 安装和卸载 查询和信息 仓库管理 维护和调试 常用选项 四.更换镜像源 常用的镜像源 更换镜像源基础操作 一.前言 Linux 的软件包管理是指在 Linux 操作系统中安…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...