JVM-类加载器和双亲委派机制

news2024/9/22 15:49:55

什么是类加载器?

类加载器是Jvm的重要组成之一(类加载器、运行时数据区、执行引擎、本地库接口、本地方法库),负责读取java字节码并将其加载到Jvm中的组件

类加载器的分类

Java中的类加载器可以分为以下几种:

1. 启动类加载器(Bootstrap ClassLoader)
  • 定义:这是最顶层的类加载器,用于加载Java核心类库(如java.lang.*java.util.*等)。
  • 实现:启动类加载器是由本地代码(通常是C/C++)实现的,并不是一个Java类。
  • 加载路径:它加载位于<JAVA_HOME>/lib目录下的类文件。
2. 扩展类加载器(Extension ClassLoader)
  • 定义:用于加载扩展类库(通常是标准类库的扩展)。
  • 实现:由sun.misc.Launcher$ExtClassLoader类实现。
  • 加载路径:它加载位于<JAVA_HOME>/lib/ext目录下的类文件,或者由java.ext.dirs系统属性指定的路径。
3. 应用程序类加载器(Application ClassLoader)
  • 定义:又称为系统类加载器(System ClassLoader),用于加载应用程序的类文件。
  • 实现:由sun.misc.Launcher$AppClassLoader类实现。
  • 加载路径:它加载由CLASSPATH环境变量或java.class.path系统属性指定的路径中的类文件。
4. 自定义类加载器(Custom ClassLoader)
  • 定义:自定义类加载器是由开发者定义的类加载器,用于从特定来源加载类文件。通过自定义类加载器,可以实现从文件系统、网络、数据库等非标准路径加载类文件。
  • 实现:自定义类加载器通常通过继承java.lang.ClassLoader类并重写其方法来实现。例如,重写findClass方法来定义类的加载逻辑。
  • 加载路径:自定义类加载器可以从任何指定的路径加载类文件,这取决于自定义的实现逻辑。

类加载器的双亲委派模型

Java采用了双亲委派模型(Parent Delegation Model)来管理类加载器的层次结构。在这种模型中,每个类加载器在尝试加载类之前,会先委派给它的父类加载器加载。只有当父类加载器无法找到该类时,子加载器才会尝试加载。

例如当一个自定义类加载器试图加载一个类,它会先委派应用程序类加载器,如何应用程序类加载器会委派扩展类加载器,扩展类加载器会委派启动类加载器,启动类加载器先看一下自己有没有这个类,没有就让扩展类去加载,有的话直接自己加载,同理,扩展类也会先看有没有,没有的话让应用程序类加载,应用程序类也是同理。假如所有类加载器都没有该类,则会抛出ClassNotFoundException异常。

如图,自定义类加载器的父类加载器通常是应用程序类加载器(可改),应用程序的父类加载器是扩展类加载器,扩展类加载器的父类加载器是启动类加载器。值得一提的是,父类加载器是用类种的一个成员变量(parent)存储的,而因为启动类加载器特俗的地位和职责,无法在java中获取到,所以实际上扩展类加载器的parent存放的是一个null,实际需要调用启动类加载器时会通过特殊的方法实现。通过getClassLoader()方法去获得启动类加载器返回的也是null。

双亲委派模型的好处
  1. 安全性:防止核心类库被自定义类覆盖,提高系统的安全性。
  2. 避免重复加载:确保类只被加载一次,提高性能和内存利用率。

打破双亲委派机制的三种方法

一、自定义类加载器

自定义一个类加载,重写loadClass()方法,清除双亲委派机制的代码,实例:

@Override
    public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // 检查类是否已经加载
        Class<?> c = findLoadedClass(name);

        // 如果类未被加载,尝试加载类
        if (c == null) {
            try {
                // 自定义类加载逻辑
                c = findClass(name);
            } catch (ClassNotFoundException e) {
                // 如果找不到类,再尝试使用父类加载器加载
                if (getParent() != null) {
                    c = getParent().loadClass(name);
                } else {
                    throw new ClassNotFoundException(name);
                }
            }
        }

        // 如果需要链接类
        if (resolve) {
            resolveClass(c);
        }

        return c;
    }
二、利用线程上下文类加载器

调用线程上下文类加载器(通常是应用程序类加载器)来打破双亲委派机制,思路是当一个类的类加载器是启动类或扩展类加载器时,是无法通过双亲委派机制去委派到应用程序类加载器的,假如需要加载的类又只有应用程序类加载器中有,那么此时就可以通过线程上下文类加载器去加载,因为线程上下文类加载器通常保存的是应用程序类加载器。

// 获取当前线程的上下文类加载器
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
利用线程上下文类加载器到底有没有打破双亲委派机制?

在笔者看来是没有直接打破双亲委派机制的,因为线程上下文类加载器依然是按照双亲委派机制去加载类,线程上下文类加载器只是提供了一种更灵活的方式去加载类。

三、OSGI框架的类加载器

OSGI框架自己实现了一套类加载机制打破了双亲委派机制,在OSGI中允许同级类互相委派,并且OSGI还使用类加载器实现了项目的热部署。

总结

类加载器:加载 Java 类字节码到 JVM 的组件,负责类的查找、加载和连接。

类加载器的分类

  1. 启动类加载器(Bootstrap ClassLoader):加载核心 Java 类库。
  2. 扩展类加载器(Extension ClassLoader):加载扩展类库。
  3. 应用类加载器(Application ClassLoader):加载应用程序类。

双亲委派机制:类加载请求先递交给父类加载器处理,避免重复加载和确保核心类安全。

打破双亲委派机制的三种方法

  1. 自定义类加载器:自定义逻辑加载类,绕过父类加载。
  2. 线程上下文类加载器:通过修改线程的上下文类加载器,动态选择类加载器。
  3. 使用 OSGi 框架:OSGi 自带的类加载机制支持模块化和隔离,突破双亲委派。

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

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

相关文章

Yolov8在RK3588上进行自定义目标检测(一)

1.数据集和训练模型 项目地址&#xff1a;https://github.com/airockchip/ultralytics_yolov8.git 从github(htps:l/github.com/airockchip/ultralytics_yolov8)上获取yolov8模型。 下载项目&#xff1a; git clone https://github.com/airockchip/ultralytics_yolov8.git …

进程的虚拟内存地址(C++程序的内存分区)

严谨的说法&#xff1a; 一个C、C程序实际就是一个进程&#xff0c;那么C的内存分区&#xff0c;实际上就是一个进程的内存分区&#xff0c;这样的话就可以分为两个大模块&#xff0c;从上往下&#xff0c;也就是0地址一直往下&#xff0c;假如是x86的32位Linux系统&#xff0c…

InstantID节点安装遇到的问题与解决办法

原来在一台没有显卡支持的电脑上安装InstantID节点使用没有问题&#xff0c;将安装好的ComfyUI&#xff08;简称ComfyUI_CPU_OK包&#xff09;复制到一台有显卡支持的电脑上&#xff0c;竟然发现InstantID节点异常不能使用&#xff08;按道理应该能正常运行才对&#xff09;&am…

吴恩达机器学习L1W3L06-逻辑回归的梯度下降

目标 在本实验室&#xff0c;你可以看到 更新逻辑回归的梯度下降。在一个熟悉的数据集上探索梯度下降 import copy, math import numpy as np %matplotlib widget import matplotlib.pyplot as plt from lab_utils_common import dlc, plot_data, plt_tumor_data, sigmoid,…

SQL注入实例(sqli-labs/less-3)

0、初始页面 1、确定闭合字符 确定为字符型注入 ?id1 and 11 ?id1 and 12 确定闭合字符为 ‘) ?id1 ?id1) 2、确定表的列数 确定查询表的列数为3 ?id1) order by 3 -- 3、确定回显位置 确定回显位置为第二列和第三列 ?id-1) union select 1,2,3 -- 4、爆库名 …

MySQL数据库——数据库基础

二、数据库基础 1.主流数据库 SQL Sever:微软的产品&#xff0c;.Net程序员的最爱&#xff0c;中大型项目。Oracle:甲骨文产品&#xff0c;适合大型项目&#xff0c;复杂的业务逻辑&#xff0c;并发一般来说不如MySQL。MySQL&#xff1a;世界上最受欢迎的数据库&#xff0c;属…

《Advanced RAG》-01-朴素RAG存在的问题

摘要 文章阐述了RAG技术如何通过整合外部知识源来提升大型语言模型&#xff08;LLM&#xff09;的性能&#xff0c;使其能够产生更精确、上下文感知的回应&#xff0c;并减少幻觉现象。 自2023年以来&#xff0c;RAG已成为基于LLM的系统中最流行的架构&#xff0c;许多产品依赖…

一文彻底搞懂Fine-tuning - 预训练和微调(Pre-training vs Fine-tuning)

最近这一两周看到不少互联网公司都已经开始秋招提前批了。不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友解…

推荐算法学习记录2.2——kaggle数据集的动漫电影数据集推荐算法实践——基于内容的推荐算法、协同过滤推荐

1、基于内容的推荐&#xff1a; 这种方法根据项的相关信息&#xff08;如描述信息、标签等&#xff09;和用户对项的操作行为&#xff08;如评论、收藏、点赞等&#xff09;来构建推荐算法模型。它可以直接利用物品的内容特征进行推荐&#xff0c;适用于内容较为丰富的场景。‌…

VBA学习(22):动态显示日历

这是在ozgrid.com论坛上看到的一个贴子&#xff0c;很有意思&#xff0c;本来使用公式是可以很方便在工作表中实现日历显示的&#xff0c;但提问者因其需要&#xff0c;想使用VBA实现动态显示日历&#xff0c;即根据输入的年份和月份在工作表中显示日历。 下面是实现该效果的VB…

web、nginx

一、web基本概念和常识 ■ Web:为用户提供的一种在互联网上浏览信息的服务,Web服务是动态的、可交互的、跨平台的和图形化的。 ■ Web 服务为用户提供各种互联网服务,这些服务包括信息浏览服务,以及各种交互式服务,包括聊天、购物、学习等等内容。 ■ Web 应用开发也经过了几…

C#中计算矩阵(数学库下载和安装)

1、一步步建立一个C#项目 一步步建立一个C#项目(连续读取S7-1200PLC数据)_s7协议批量读取-CSDN博客文章浏览阅读1.7k次&#xff0c;点赞2次&#xff0c;收藏4次。这篇博客作为C#的基础系列&#xff0c;和大家分享如何一步步建立一个C#项目完成对S7-1200PLC数据的连续读取。首先…

如何解决C#字典的线程安全问题

前言 我们在上位机软件开发过程中经常需要使用字典这个数据结构&#xff0c;并且经常会在多线程环境中使用字典&#xff0c;如果使用常规的Dictionary就会出现各种异常&#xff0c;本文就是详细介绍如何在多线程环境中使用字典来解决线程安全问题。 1、非线程安全举例 Dictio…

文件搜索 36

删除文件 文件搜索 package File;import java.io.File;public class file3 {public static void main(String[] args) {search(new File("D :/"), "qq");}/*** 去目录搜索文件* param dir 目录* param filename 要搜索的文件名称*/public static void sear…

探索Prefect:Python自动化的终极武器

文章目录 探索Prefect&#xff1a;Python自动化的终极武器背景&#xff1a;自动化的呼唤Prefect&#xff1a;自动化的瑞士军刀安装Prefect&#xff1a;一键启动基础用法&#xff1a;Prefect的五招场景应用&#xff1a;Prefect的实战演练常见问题&#xff1a;Prefect的故障排除总…

字节一面面经

1.redis了解吗&#xff0c;是解决什么问题的&#xff0c;redis的应用&#xff1f; Redis 是一种基于内存的数据库&#xff0c;常用的数据结构有string、hash、list、set、zset这五种&#xff0c;对数据的读写操作都是在内存中完成。因此读写速度非常快&#xff0c;常用于缓存&…

IDEA的疑难杂症

注意idea版本是否与maven版本兼容 2019idea与maven3.6以上不兼容 IDEA无法启动 打开idea下载安装的目录&#xff1a;如&#xff1a;Idea\IntelliJ IDEA 2024.1\bin 在bin下面找到 打开在最后一行添加暂停 pause 之后双击运行idea.bat 提示找不到一个jar包&#xff0c;…

MyBatis 框架的两大缺点及解决方案

MyBatis 框架的两大缺点及解决方案 1. SQL 编写负担重1.1 缺点概述1.2 解决方案 2. 数据库移植性差2.1 缺点概述2.2 解决方案 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; MyBatis 作为一款广受欢迎的 Java 持久层框架&#xff0c;尽管其…

ssh 显示图形化界面 Error: Can‘t open display

在客户端&#xff08;你自己的电脑&#xff0c;不是服务器&#xff09;安装 VcXsrv 直接从 github 上下载 https://github.com/marchaesen/vcxsrv/releases&#xff0c;或者使用 winget 命令 winget install -i vcxsrv在服务器上 ~/.zshrc 中&#xff08;或 ~/.bashrc&#xf…

【ubuntu系统】在虚拟机内安装Ubuntu

Ubuntu系统装机 描述新装机后的常规配置&#xff0c; 虚拟机使用vbox terminal 打不开 CTRL ALT F3 进入命令行模式&#xff08;需要返回桌面时CTRL ALT F1&#xff09;root用户登入cd /etc/default vi locale LANG“en_US” 改成 LANG“en_US.UTF-8”保存修改后&…