【Java从入门到放弃 之 类加载器】

news2025/1/14 17:08:03

类加载器 ClassLoader

  • 类加载器
  • 动态加载类的两种方式
  • 类加载过程
  • 双亲委派模型
    • 特点
    • 类加载器层次结构
  • 自定义类加载器
  • 总结

类加载器

类加载器负责将Java字节码文件(.class文件)动态加载到内存中,并将其转化为JVM可以执行的类对象。它是Java运行时系统的一部分,支持Java的动态特性,使得Java程序可以在运行时加载类和接口。

动态加载类的两种方式

public class ClassLoaderTest {
    static {
        System.out.println("ClassLoaderTest");
    }
}
public class Test24 {
    public static void main(String[] args) throws ClassNotFoundException {
        loadClass1();
    }

    // 使用ClassLoader.loadClass
    public static void loadClass1() throws ClassNotFoundException {
        Class<?> testClass = Test24.class.getClassLoader()
                .loadClass("com.example.mydemo.test.ClassLoaderTest");
        System.out.println(testClass.getName());
    }
    // 使用Class.forName
    public static void loadClass2() throws ClassNotFoundException {
        Class<?> testClass = Class.forName(
                "com.example.mydemo.test.ClassLoaderTest");
        System.out.println(testClass.getName());
    }
}

输出:

com.example.mydemo.test.ClassLoaderTest
public class Test24 {
    public static void main(String[] args) throws ClassNotFoundException {
        loadClass2();
    }

    // 使用ClassLoader.loadClass
    public static void loadClass1() throws ClassNotFoundException {
        Class<?> testClass = Test24.class.getClassLoader()
                .loadClass("com.example.mydemo.test.ClassLoaderTest");
        System.out.println(testClass.getName());
    }
    // 使用Class.forName
    public static void loadClass2() throws ClassNotFoundException {
        Class<?> testClass = Class.forName(
                "com.example.mydemo.test.ClassLoaderTest");
        System.out.println(testClass.getName());
    }
}

输出:

ClassLoaderTest
com.example.mydemo.test.ClassLoaderTest

不同之处
很明显,class.forname方法除法了静态方法,而getClassLoader().loadclass方法未出发静态方法。

类加载过程

类加载过程可以分为以下几个步骤:

  1. 加载(Loading):在加载阶段,类加载器通过类的全限定名(如java.lang.String)查找对应的字节码文件,并将其加载到内存中。这一过程通常从文件系统、JAR包或网络等资源中读取字节码文件。
  2. 链接(Linking):链接过程将类的字节码合并到JVM的运行时环境中。这一步包括验证、准备和解析。
  3. 验证(Verification):验证字节码文件的正确性,确保其符合JVM规范。
  4. 准备(Preparation):为类的静态变量分配内存,并初始化默认值(注意,这里只是初始化为数据类型对应的零值,而不是代码中设置的默认值)。
  5. 解析(Resolution):将符号引用转换为直接引用,即将类中的符号(如方法、字段)解析为实际内存地址。
  6. 初始化(Initialization):执行类的静态初始化块和静态变量的赋值操作。例如,当类的静态变量或静态代码块被首次使用时,初始化将自动发生。

双亲委派模型

双亲委派模型(Parent Delegation Model):当一个类加载器试图加载某个类时,它会先将这个请求委托给父类加载器,而不是自己直接加载。只有当父类加载器无法找到该类时,才由当前类加载器尝试加载。

特点

  • 这种机制确保了Java核心类库不会被用户自定义的类加载器替代或覆盖。
  • 子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。
  • 仅加载一个类一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类。

类加载器层次结构

在这里插入图片描述
如果你有英文基础的话,可以阅读一下官方对类加载器的文章

自定义类加载器

除了使用JVM提供的默认类加载器外,开发人员还可以根据需要自定义类加载器。自定义类加载器通常需要继承java.lang.ClassLoader类,并重写其中的findClass()方法或loadClass()方法。通过自定义类加载器,可以实现一些特殊的功能,如从网络加载类、从数据库加载类等。

** 为啥有系统类加载器还需要自定义类加载器呢**
我们通过创建自定义类加载器,可以实现Tomcat应用隔离 支持jsp OSGI实现动态模块化。这些听起来比较晕是吧。 Java同一个类被不同的类加载器加载会得到同一个类的不同Class对象。

public class Test26 {


    public static void main(String[] args) throws ClassNotFoundException {
        MyClassLoader myClassLoader = new MyClassLoader();
        Class<?> aClass = myClassLoader.loadClass("com.example.mydemo.test.Test1");
        MyClassLoader myClassLoader1 = new MyClassLoader();
        Class<?> bClass = myClassLoader1.loadClass("com.example.mydemo.test.Test1");
        if (aClass != bClass) {
            System.out.println("aClass is different from bClass");
        }
    }
}

aClass 跟 bClass 是不同的对象。

** 这有啥用呢**

  1. 一个程序可能有多个模块,模块之间的可能使用的同一个类,但是不同的版本。如果我们都使用系统自带的加载器,就无法达到这个效果。通过自定义类加载器,我们就可以得到不同的类。实现隔离。
  2. 实现热部署,同一个类只会被classloader加载一次,所以当我们更改完代码,即使class变了,也不会被原来的加载器在重新加载。而通过自定义类加载器,我们每一次都是new一个新的自定义类加载器,这样我们就每次都可以得到一个新的Class对象,从而实现动态更新。
    (所谓热部署,就是在不重启应用的情况下,当类的定义即字节码文件修改后,能够替换该Class创建的对象)

总结

我们主要介绍了类加载机制与双亲委派模型,另外重点介绍了自定义类加载器。希望能给你带去帮助。也欢迎大家留言,评论,私信。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2253068.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为HarmonyOS 让应用快速拥有账号能力 -- 1 华为账号一键登录

概述 华为账号一键登录是基于OAuth 2.0协议标准和OpenID Connect协议标准构建的OAuth2.0 授权登录系统&#xff0c;应用可以通过华为账号一键登录能力方便地获取华为账号用户的身份标识和手机号&#xff0c;快速建立应用内的用户体系。 优势&#xff1a; 利用系统账号的安全…

高效数据分析:五款报表工具助力企业智能决策

概述 报表工具是企业进行数据分析、展示和决策支持的核心工具之一。本文将为大家介绍五款各具特色的报表工具&#xff0c;包括国产的山海鲸报表、FineReport&#xff0c;以及国际工具Databox、Pentaho Reporting和Zoho Analytics。通过详细分析它们的功能特点、优势和不足&…

生态环境一体化智慧监管平台

在数字化和智能化的浪潮中&#xff0c;生态环境保护与治理正迎来革命性的变化。生态环境一体化智慧监管平台的建设&#xff0c;不仅响应了这一趋势&#xff0c;而且为中国式现代化的生态治理提供了新的解决方案。本文将深度分析该平台的建设内容&#xff0c;探讨其在推动生态文…

基于PyTorch框架的线性回归实现指南

目录 ​编辑 1. 线性回归基础 2. PyTorch环境搭建 3. 数据准备 4. 定义线性回归模型 5. 损失函数和优化器 6. 训练模型 7. 评估模型 8. 结论 线性回归是统计学和机器学习中最基本的预测模型之一&#xff0c;它试图找到输入特征和输出结果之间的线性关系。在深度学习框…

重生之我在异世界学编程之C语言:深入指针篇(下)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 目录 题集&#xff08;1&#xff09;指针笔试题1&a…

【HarmonyOS】鸿蒙应用地理位置获取,地理名称获取

【HarmonyOS】鸿蒙应用地理位置获取&#xff0c;地理名称获取 一、前言 首先要理解地理专有名词&#xff0c;当我们从系统获取地理位置&#xff0c;一般会拿到地理坐标&#xff0c;是一串数字&#xff0c;并不是地理位置名称。例如 116.2305&#xff0c;33.568。 这些数字坐…

SimpleLive1.7.5 |适配手机和TV,聚合抖B虎鱼四大直播

SimpleLive是一款聚合多个直播平台的应用程序&#xff0c;内置虎牙、斗鱼、哔哩哔哩及抖音直播。提供无广告体验&#xff0c;支持弹幕显示调整、夜间模式切换等功能。用户无需登录即可关注不同平台的主播并查看其直播状态。 大小&#xff1a;14M 下载地址&#xff1a; 百度网…

泷羽sec:shell作业

⼀、⽤Shell写⼀个计算器 #!/bin/bash read -p "请输入表达式&#xff08;格式为 操作数1 运算符 操作数2&#xff0c;如 5 3&#xff09;&#xff1a;" expression a1$(echo $expression | awk {print $1}) a2$(echo $expression | awk {print $2}) a3$(echo …

ETL工具观察:ETLCloud与MDM是什么关系?

一、什么是ETLCloud ETLCloud数据中台是一款高时效的数据集成平台&#xff0c;专注于解决大数据量和高合规要求环境下的数据集成需求。 工具特点 1.离线与实时集成&#xff1a;支持离线数据集成&#xff08;ETL、ELT&#xff09;和变更数据捕获&#xff08;CDC&#xff09;实…

轻NAS系统CasaOS设备安装小雅超集结合内网穿透实现自由访问海量资源

文章目录 前言1. 本地部署AList2. AList挂载网盘3. 部署小雅alist3.1 Token获取3.2 部署小雅3.3 挂载小雅alist到AList中 4. Cpolar内网穿透安装5. 创建公网地址6. 配置固定公网地址 前言 本文主要介绍如何在安装了轻NAS系统CasaOS的小主机中部署小雅AList&#xff0c;并使用A…

MATLAB 最小二乘点云拟合球 (89)

MATLAB 最小二乘点云拟合球 (89) 一、算法介绍二、算法实现1.代码2.结果这是缘,亦是最美的相见 一、算法介绍 球面拟合算法是一种通过数学方法将一组三维点(通常在三维空间中分布)拟合到一个理想的球形表面上。这个过程通常涉及使用最小二乘法来最小化实际数据点与拟合的…

【分页查询】.NET开源 ORM 框架 SqlSugar 系列

&#x1f4a5; .NET开源 ORM 框架 SqlSugar 系列 &#x1f389;&#x1f389;&#x1f389; 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列…

WebStorm快捷键保持跟Idea一致

修改连续行局部多选 在WebStorm中同时按下ctrl alt s&#xff1b; 选择KeyMap 输入Column Selection Mode选择快捷键, 右键选择Add Mouse Shortcut 按下alt 鼠标左键 如果出现占用的情况&#xff0c;直接删除其他使用该快捷键的地方即可&#xff1b; 修改跨行局部多选 在…

好书推荐《LangChain大模型AI应用开发实践》

Hi大家好&#xff0c;我是码银~ 今天我要给大家带来一本特别的书籍推荐——《LangChain大模型AI应用开发实践》。如果你对人工智能、自然语言处理或者正在寻找一种高效构建AI应用的方法&#xff0c;那么这本书绝对不容错过。 这本书是由哔哩哔哩知名UP主【老陈打码】&#xff0…

python使用openpyxl处理excel

文章目录 一、写在前面1、安装openpyxl2、认识excel窗口 二、基本使用1、打开excel2、获取sheet表格3、获取sheet表格 尺寸4、获取单元格数据5、获取区域单元格数据6、sheet.iter_rows()方法7、修改单元格的值8、向表格中插入行数据9、实战&#xff1a;合并多个excel 三、获取E…

Spire.PDF for .NET【页面设置】演示:旋放大 PDF 边距而不改变页面大小

PDF 页边距是正文内容和页面边缘之间的空白。与 Word 不同&#xff0c;PDF 文档中的页边距不易修改&#xff0c;因为 Adobe 不提供任何功能供用户自由操作页边距。但是&#xff0c;您可以更改页面缩放比例&#xff08;放大/压缩内容&#xff09;或裁剪页面以获得合适的页边距。…

SpringMVC:参数传递之日期类型参数传递

环境准备和参数传递请见&#xff1a;SpringMVC参数传递环境准备 日期类型比较特殊&#xff0c;因为对于日期的格式有N多中输入方式&#xff0c;比如: 2088-08-182088/08/1808/18/2088… 针对这么多日期格式&#xff0c;SpringMVC该如何接收&#xff0c;它能很好的处理日期类…

驱动篇的开端

准备 在做之后的动作前&#xff0c;因为win7及其以上的版本默认是不支持DbgPrint&#xff08;大家暂时理解为内核版的printf&#xff09;的打印&#xff0c;所以&#xff0c;为了方便我们的调试&#xff0c;我们先要修改一下注册表 创建一个reg文件然后运行 Windows Registr…

Spring 那些事【2】SpringCache 简介及应用?

一、简介 SpringCache 是Spring 提供的一整套的缓存解决方案&#xff0c;他不是具体的缓存实现&#xff0c;它只提供了一整套的接口和代码规范、配置、注解等&#xff0c;用于整合各种缓存方案。 Spring 从 3.1 开始定义了 org.springframework.cache.Cache 和 org.springfra…

C语言:指针与数组

一、. 数组名的理解 int arr[5] { 0,1,2,3,4 }; int* p &arr[0]; 在之前我们知道要取一个数组的首元素地址就可以使用&arr[0]&#xff0c;但其实数组名本身就是地址&#xff0c;而且是数组首元素的地址。在下图中我们就通过测试看出&#xff0c;结果确实如此。 可是…