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

Java_类加载器

  • 小程一言
  • 类加载器的基础
    • 双亲委派模型
      • 核心思想
      • 优势
    • 各类加载器的职责
  • 类加载器的工作流程
  • 举例:如何在Java中使用类加载器
    • 启动类加载器、扩展类加载器与系统类加载器
    • 输出
    • 解释
    • 自定义类加载器
  • 类加载器与类冲突
  • 总结

小程一言

本专栏是对Java知识点的总结。在学习Java的过程中,学习的笔记,加入自己的思考,结合各种资料的整理。

文章与程序一样,一定都是不完美的,因为不完美,才拥有不断追求完美的动力

类加载器的基础

首先要明确类加载器的职责就是加载类。当JVM启动时,系统会使用类加载器将必要的类(如java.lang.*类库)加载到内存中。Java中的类加载器是递归结构,遵循“双亲委派模型”。

双亲委派模型

核心思想

当一个类加载器接到加载类的请求时,它不会立即去加载该类,而是先将请求委派给它的父类加载器。只有当父类加载器无法完成加载时,子类加载器才会尝试自己加载。

优势

它保证了Java的核心类库(如java.lang.String)始终由系统的启动类加载器来加载,避免了“重复加载”问题,并增加了类加载的安全性。

双亲委派模型的加载顺序:

  1. 启动类加载器
  2. 扩展类加载器
  3. 系统类加载器
  4. 自定义类加载器
    在这里插入图片描述

各类加载器的职责

  • 启动类加载器(Bootstrap ClassLoader):负责加载JVM的核心类库,如java.lang.*包中的类。它是Java中最底层的类加载器,通常由C或C++编写,并且由JVM本身提供。

  • 扩展类加载器(Extension ClassLoader):负责加载jre/lib/ext目录下的类或JVM扩展目录中的类。它的父类是启动类加载器。

  • 系统类加载器(System ClassLoader):负责加载应用程序的类路径(Classpath)中指定的类。它通常是由用户定义的类所在的目录、JAR包等。

  • 自定义类加载器(Custom ClassLoader):由开发者自定义的类加载器,可以扩展现有的类加载器,来加载类文件、网络上的类、数据库中的类等。

类加载器的工作流程

类加载器的工作流程可以简单分为以下几个步骤:

  1. 加载:类加载器根据类名,查找并读取相应的字节码文件(.class文件)。
  2. 验证:JVM会验证字节码文件的有效性,确保它符合Java的语言规范。
  3. 准备:为类的静态字段分配内存,并为它们赋默认值(如null0等)。
  4. 解析:将类中的符号引用转换为直接引用,主要是指将常量池中的符号,如类名、字段名、方法名等,解析为内存地址。
  5. 初始化:执行类的静态初始化代码(如静态变量的初始化和静态块的执行)。
    在这里插入图片描述

举例:如何在Java中使用类加载器

启动类加载器、扩展类加载器与系统类加载器

public class ClassLoaderExample {public static void main(String[] args) {// 获取当前类加载器ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();System.out.println("系统类加载器:" + systemClassLoader);// 获取扩展类加载器ClassLoader extClassLoader = systemClassLoader.getParent();System.out.println("扩展类加载器:" + extClassLoader);// 获取启动类加载器ClassLoader bootstrapClassLoader = extClassLoader.getParent();System.out.println("启动类加载器:" + bootstrapClassLoader);}
}

输出

系统类加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
扩展类加载器:sun.misc.Launcher$ExtClassLoader@5e91993f
启动类加载器:null

解释

  • 系统类加载器是由ClassLoader.getSystemClassLoader()返回的,它是JVM默认的类加载器。
  • 扩展类加载器系统类加载器的父加载器,它负责加载JVM的扩展库。
  • 启动类加载器扩展类加载器的父加载器,它负责加载Java的核心库。

自定义类加载器

通过继承ClassLoader类来实现自定义类加载器。假设我们有一个自定义的MyClassLoader,它从特定的目录加载类:

import java.io.*;
public class MyClassLoader extends ClassLoader {private String classPath;public MyClassLoader(String classPath) {this.classPath = classPath;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {String path = classPath + name.replace('.', File.separatorChar) + ".class";File file = new File(path);if (file.exists()) {try (FileInputStream inputStream = new FileInputStream(file)) {byte[] bytes = new byte[(int) file.length()];inputStream.read(bytes);return defineClass(name, bytes, 0, bytes.length);} catch (IOException e) {e.printStackTrace();}}return super.findClass(name);}public static void main(String[] args) throws Exception {MyClassLoader myClassLoader = new MyClassLoader("path/to/classes/");// 使用自定义类加载器加载类Class<?> clazz = myClassLoader.loadClass("com.example.MyClass");System.out.println("加载的类: " + clazz.getName());}
}

本例中,定义了一个MyClassLoader,它从指定的路径加载类文件。当你调用loadClass()时,它会尝试使用findClass()方法加载类。如果找不到,系统类加载器会被调用。

例如,在使用自定义类加载器加载完类后,如果不再需要这些类,类加载器本身也会被垃圾回收,类将被卸载。类卸载通常发生在类加载器不再有任何引用,并且类加载器本身被回收时。
在这里插入图片描述

类加载器与类冲突

有时会遇到不同的类加载器加载同一个类的情况。如下:

public class TestClass {public void printMessage() {System.out.println("Hello from TestClass!");}public static void main(String[] args) throws Exception {MyClassLoader myClassLoader1 = new MyClassLoader("path/to/classes/");MyClassLoader myClassLoader2 = new MyClassLoader("path/to/classes/");Class<?> clazz1 = myClassLoader1.loadClass("TestClass");Class<?> clazz2 = myClassLoader2.loadClass("TestClass");System.out.println("clazz1 == clazz2: " + (clazz1 == clazz2));}
}

在这个例子中,我们创建了两个不同的MyClassLoader,并用它们分别加载TestClass类。由于每个MyClassLoader加载的是不同的TestClass实例,clazz1 == clazz2将会输出false,表明它们是不同的类。
在这里插入图片描述

总结

  • Java的类加载器机制确保了类的加载、验证、链接和初始化的顺序。
  • 类加载器采用双亲委派模型,从而保证了系统类库的统一加载,避免了类的重复加载。
  • 你可以通过继承ClassLoader类来自定义类加载器,控制类的加载过程。
  • 类加载器的生命周期与JVM的生命周期相匹配,因此类会在合适的时候被卸载,防止内存泄漏。

相关文章:

Java_类加载器

小程一言类加载器的基础双亲委派模型核心思想优势 各类加载器的职责 类加载器的工作流程举例&#xff1a;如何在Java中使用类加载器启动类加载器、扩展类加载器与系统类加载器输出解释自定义类加载器 类加载器与类冲突总结 小程一言 本专栏是对Java知识点的总结。在学习Java的过…...

开源音乐管理软件Melody

本文软件由网友 heqiusheng 推荐。不过好像已经是一年前了 &#x1f602; 简介 什么是 Melody &#xff1f; Melody 是你的音乐精灵&#xff0c;旨在帮助你更好地管理音乐。目前的主要能力是帮助你将喜欢的歌曲或者音频上传到音乐平台的云盘。 主要功能包括&#xff1a; 歌曲…...

一、TensorFlow的建模流程

1. 数据准备与预处理&#xff1a; 加载数据&#xff1a;使用内置数据集或自定义数据。 预处理&#xff1a;归一化、调整维度、数据增强。 划分数据集&#xff1a;训练集、验证集、测试集。 转换为Dataset对象&#xff1a;利用tf.data优化数据流水线。 import tensorflow a…...

Vue.js组件开发-实现左侧浮动菜单跟随页面滚动

使用 Vue 实现左侧浮动菜单跟随页面滚动 实现步骤 创建 Vue 项目&#xff1a;使用 Vue CLI 创建一个新的 Vue 项目。设计 HTML 结构&#xff1a;包含一个左侧浮动菜单和一个主要内容区域。编写 CSS 样式&#xff1a;设置菜单的初始样式和滚动时的样式。使用 Vue 的生命周期钩…...

分析哲学:从 语言解剖到 思想澄清的哲学探险

分析哲学&#xff1a;从 语言解剖 到 思想澄清 的哲学探险 第一节&#xff1a;分析哲学的基本概念与公式解释 【通俗讲解&#xff0c;打比方来讲解&#xff01;】 分析哲学&#xff0c;就像一位 “语言侦探”&#xff0c;专注于 “解剖语言”&#xff0c;揭示我们日常使用的语…...

MySQL 插入数据指南

MySQL 插入数据指南 引言 MySQL 是一款广泛使用的开源关系数据库管理系统&#xff0c;被广泛应用于各种规模的组织中。在数据库管理中&#xff0c;数据的插入是基础操作之一。本文将详细介绍如何在 MySQL 中插入数据&#xff0c;包括插入单条记录和多条记录&#xff0c;以及一…...

寒假刷题Day20

一、80. 删除有序数组中的重复项 II class Solution { public:int removeDuplicates(vector<int>& nums) {int n nums.size();int stackSize 2;for(int i 2; i < n; i){if(nums[i] ! nums[stackSize - 2]){nums[stackSize] nums[i];}}return min(stackSize, …...

鸿蒙物流项目之基础结构

目录&#xff1a; 1、项目结构2、三种包的区别和使用场景3、静态资源的导入4、颜色样式设置5、修改项目名称和图标6、静态包基础目录7、组件的抽离8、在功能模块包里面引用静态资源包的组件 1、项目结构 2、三种包的区别和使用场景 3、静态资源的导入 放在har包中&#xff0c;那…...

[漏洞篇]SQL注入漏洞详解

[漏洞篇]SQL注入漏洞详解 介绍 把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串&#xff0c;最终达到欺骗服务器执行恶意的SQL命令。通过构造恶意的输入&#xff0c;使数据库执行恶意命令&#xff0c;造成数据泄露或者修改内容等&#xff0c;以达到攻击的目的。…...

【最后203篇系列】006 -使用ollama运行deepseek-r1前后端搭建

说明 这块已经不算新内容了&#xff0c;年前搭完了后端&#xff08;ollama)&#xff0c;本来想早点分享的&#xff0c;但是当时的openwebui有点不给力&#xff0c;有些地方不适配&#xff0c;然后配置项找不到。所以前端没搭好&#xff0c;也就不完整&#xff1a;只能通过命令…...

CSS Module 常用笔记

Date: January 30, 2025 CSS 先介绍下普通 CSS&#xff0c;再简明介绍下 css module 的使用 普通 CSS 内联 style 定义&#xff1a; 内联 style 是通过在元素的 style 属性中直接设置 CSS 样式。这种方式允许我们直接在 JSX 中为组件或元素添加样式。 写法&#xff1a; &…...

JDK-1.8.0_432安装(CentOS7)

目录 1、卸载系统自带JDK 2、下载安装包并解压 3、赋予可执行权限 4、设置环境变量 5、刷新环境变量 6、查看JDK版本 1、卸载系统自带JDK # 查询出自带的jdk rpm -qa | grep jdk rpm -qa | grep java # 将上述命令列出的包依次删除 rpm -e --nodeps xxxxxxx 2、下载…...

【Linux】24.进程信号(1)

文章目录 1. 信号入门1.1 进程与信号的相关知识1.2 技术应用角度的信号1.3 注意1.4 信号概念1.5 信号处理常见方式概览 2. 产生信号2.1 通过终端按键产生信号2.2 调用系统函数向进程发信号2.3 由软件条件产生信号2.4 硬件异常产生信号2.5 信号保存 3. 阻塞信号3.1 信号其他相关…...

C++ 字面量深度解析:从基础到实战进阶

在 C 开发中&#xff0c;字面量&#xff08;Literal&#xff09;不仅是基础语法的一部分&#xff0c;更是提升代码可读性、安全性和性能的关键工具。本文将深入探讨 C 字面量的高级特性、最新标准支持&#xff08;C11/14/17/20&#xff09;以及实际开发中的应用技巧&#xff0c…...

股票入门知识

股票入门&#xff08;更适合中国宝宝体制&#xff09; 股市基础知识 本文介绍了股票的基础知识&#xff0c;股票的分类&#xff0c;各板块发行上市条件&#xff0c;股票代码&#xff0c;交易时间&#xff0c;交易规则&#xff0c;炒股术语&#xff0c;影响股价的因素&#xf…...

用Python实现K均值聚类算法

在数据挖掘和机器学习领域&#xff0c;聚类是一种常见的无监督学习方法&#xff0c;用于将数据点划分为不同的组或簇。K均值聚类算法是其中一种简单而有效的聚类算法。今天&#xff0c;我将通过一个具体的Python代码示例&#xff0c;向大家展示如何实现K均值聚类算法&#xff0…...

Flask代码审计实战

文章目录 Flask代码审计SQL注入命令/代码执行反序列化文件操作XXESSRFXSS其他 审计实战后记reference Flask代码审计 SQL注入 1、正确的使用直白一点就是&#xff1a;使用”逗号”&#xff0c;而不是”百分号” stmt "SELECT * FROM table WHERE id?" connectio…...

Unity 2D实战小游戏开发跳跳鸟 - 跳跳鸟碰撞障碍物逻辑

在有了之前创建的可移动障碍物之后,就可以开始进行跳跳鸟碰撞到障碍物后死亡的逻辑,死亡后会产生一个对应的效果。 跳跳鸟碰撞逻辑 创建Obstacle Tag 首先跳跳鸟在碰撞到障碍物时,我们需要判定碰撞到的是障碍物,可以给障碍物的Prefab预制体添加一个Tag为Obstacle,添加步…...

【玩转 Postman 接口测试与开发2_015】第12章:模拟服务器(Mock servers)在 Postman 中的创建与用法(含完整实测效果图)

《API Testing and Development with Postman》最新第二版封面 文章目录 第十二章 模拟服务器&#xff08;Mock servers&#xff09;在 Postman 中的创建与用法1 模拟服务器的概念2 模拟服务器的创建2.1 开启侧边栏2.2 模拟服务器的两种创建方式2.3 私有模拟器的 API 秘钥的用法…...

mysql操作语句与事务

数据库设计范式 数据库设计的三大范式 ‌第一范式&#xff08;1NF&#xff09;‌&#xff1a;要求数据库表的每一列都是不可分割的原子数据项&#xff0c;即列中的每个值都应该是单一的、不可分割的实体。例如&#xff0c;如果一个表中的“地址”列包含了省、市、区等多个信息…...

android Camera 的进化

引言 Android 的camera 发展经历了3个阶段 &#xff1a; camera1 -》camera2 -》cameraX。 正文 Camera1 Camera1 的开发中&#xff0c;打开相机&#xff0c;设置参数的过程是同步的&#xff0c;就跟用户实际使用camera的操作步骤一样。但是如果有耗时情况发生时&#xff0c;会…...

ASP.NET Core Filter

目录 什么是Filter&#xff1f; Exception Filter 实现 注意 ActionFilter 注意 案例&#xff1a;自动启用事务的筛选器 事务的使用 TransactionScopeFilter的使用 什么是Filter&#xff1f; 切面编程机制&#xff0c;在ASP.NET Core特定的位置执行我们自定义的代码。…...

Git 的起源与发展

序章&#xff1a;版本控制的前世今生 在软件开发的漫长旅程中&#xff0c;版本控制犹如一位忠诚的伙伴&#xff0c;始终陪伴着开发者们。它的存在&#xff0c;解决了软件开发过程中代码管理的诸多难题&#xff0c;让团队协作更加高效&#xff0c;代码的演进更加有序。 简单来…...

基于SpringBoot电脑组装系统平台系统功能实现五

一、前言介绍&#xff1a; 1.1 项目摘要 随着科技的进步&#xff0c;计算机硬件技术日新月异&#xff0c;包括处理器&#xff08;CPU&#xff09;、主板、内存、显卡等关键部件的性能不断提升&#xff0c;为电脑组装提供了更多的选择和可能性。不同的硬件组合可以构建出不同类…...

【智力测试——二分、前缀和、乘法逆元、组合计数】

题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; const int mod 1e9 7; const int N 1e5 10; int r[N], c[N], f[2 * N]; int nr[N], nc[N], nn, nm; int cntr[N], cntc[N]; int n, m, t;void init(int n) {f[0] f[1] 1;for (int i …...

第 1 天:UE5 C++ 开发环境搭建,全流程指南

&#x1f3af; 目标&#xff1a;搭建 Unreal Engine 5&#xff08;UE5&#xff09;C 开发环境&#xff0c;配置 Visual Studio 并成功运行 C 代码&#xff01; 1️⃣ Unreal Engine 5 安装 &#x1f539; 下载与安装 Unreal Engine 5 步骤&#xff1a; 注册并安装 Epic Game…...

axios如何利用promise无痛刷新token

目录 需求 需求解析 实现思路 方法一&#xff1a; 方法二&#xff1a; 两种方法对比 实现 封装axios基本骨架 instance.interceptors.response.use拦截实现 问题和优化 如何防止多次刷新token 同时发起两个或以上的请求时&#xff0c;其他接口如何重试 最后完整代…...

玉米苗和杂草识别分割数据集labelme格式1997张3类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;1997 标注数量(json文件个数)&#xff1a;1997 标注类别数&#xff1a;3 标注类别名称:["corn","weed","Bean…...

【自学笔记】GitHub的重点知识点-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 GitHub使用指南详细知识点一、GitHub基础与账户管理1. GitHub简介2. 创建与管理GitHub账户3. 创建与配置仓库&#xff08;Repository&#xff09; 二、Git基础与Git…...

string例题

一、字符串最后一个单词长度 题目解析&#xff1a;由题输入一段字符串或一句话找最后一个单词的长度&#xff0c;也就是找最后一个空格后的单词长度。1.既然有空格那用我们常规的cin就不行了&#xff0c;我们这里使用getline,2.读取空格既然是最后一个空格后的单词&#xff0c;…...