【JVM】双亲委派机制、打破双亲委派机制

news2025/1/18 14:58:54

在这里插入图片描述

🐌个人主页: 🐌 叶落闲庭
💨我的专栏:💨
c语言
数据结构
javaEE
操作系统
Redis

石可破也,而不可夺坚;丹可磨也,而不可夺赤。


JVM

  • 一、双亲委派机制
    • 1.1 双亲委派的作用
    • 1.2 什么是双亲委派机制
    • 1.3 双亲委派机制问题
    • 1.4 面试题(类的双亲委派机制是什么)
  • 二、打破双亲委派机制
    • 2.1 自定义类加载器

一、双亲委派机制

由于)va虚拟机中有多个类加载器,双亲委派机制的核心是解决一个类到底由谁加载的问题。

1.1 双亲委派的作用

  • 保证类加载的安全性:
    • 通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。
  • 避免重复加载:
    • 双亲委派机制可以避免同一个类被多次加载。

1.2 什么是双亲委派机制

  • 双亲委派机制指的是:当一个类加载器接收到加载类的任务时,会自底向上查找是否加载过,再由顶向下进行加载。

在这里插入图片描述


假设在com.practice包下有一个类A.java,应用程序类加载器接收到一个任务,他要去加载A.java这个类,首先他会检查一下这个类有没有被加载过,发现没有被加载过,那么他就会把这个类委派给它的父类(扩展类加载器),扩展类加载器发现也没有加载过,继续向上委派,委派给它的父亲(启动类加载器),启动类加载器发现A.java曾经加载过,所以它直接把A.java类的class对象返回,加载过程结束。
如果所有的父类加载器都无法加载该类,则由当前类加载器自己尝试加载。所以看上去是自顶向下尝试加载。
假设在com.practice包下有一个类B.java,三个类加载器都没有加载过,此时会首先从顶部(启动类加载器)尝试进行加载,发现这个类不在当前类加载器的加载路径当中,就把这个任务委派给它的下级(扩展类记载器),此时刚好有这个类的加载路径,就会进行加载,而当应用类加载器要加载B.java时,首先还是对他的父类进行查找,判断是否加载过,加载过,则返回这个类的class对象
向下委派起到了一个加载优先级的作用

1.3 双亲委派机制问题

  • 重复的类:
    • 如果一个类重复出现在三个类加载器的加载位置,应该由谁来加载?

答案应该是启动类加载器加载,因为根据双亲委派机制,它的优先级是最高的

  • String类能覆盖吗
    • 在自己的项目中去创建一个java.lang.String类,会被加载吗

不能,会返回启动类加载器加载在rt.jar包中的String类

1.4 面试题(类的双亲委派机制是什么)

1、当一个类加载器去加载某个类的时候,会自底向上向父类查找是否加载过,如果加载过就直接返回,如果一直到最顶层的类加载器都没有加载,再由顶向下进行加载。
2、应用程序类加载器的父类加载器是扩展类加载器,扩展类加载器的父类加载器是启动类加载器。
3、双亲委派机制的好处有两点:第一是避免恶意代码替换DK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。第二是避免一个类重复地被加载

二、打破双亲委派机制

2.1 自定义类加载器

  • 双亲委派机制的核心代码(源码):
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
  • 自定义类加载器:
public class BreakClassLoader1 extends ClassLoader {
    private String basePath;
    private final static String FILE_EXT = ".class";

    public void setBasePath(String basePath) {
        this.basePath = basePath;
    }

    private byte[] loadClassDate(String name) throws IOException {
        String path = basePath + File.separatorChar + name.replace('.', File.separatorChar) + FILE_EXT; // 将包名转换为文件路径
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            is = new FileInputStream(path);
            baos = new ByteArrayOutputStream();
            int bufferSize = 4096;
            byte[] buffer = new byte[bufferSize];
            int bytesNumRead = 0;
            while ((bytesNumRead = is.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesNumRead);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classDate = new byte[0];
        try {
            classDate = loadClassDate(name);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (classDate == null) {
            throw new ClassNotFoundException();
        } else {
            return defineClass(name,classDate,0,classDate.length);
        }
    }

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        BreakClassLoader1 classLoader1 = new BreakClassLoader1();
        classLoader1.setBasePath("D:\\lib\\");
        Class<?> clazz1 = classLoader1.loadClass("com.practice.Student");
        clazz1.newInstance();
        System.out.println(clazz1.getClassLoader());
    }
}

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

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

相关文章

Jetpack:028-Jetpack中的Card

文章目录 1. 概念介绍2. 使用方法2.1 主要类型2.2 其它类型 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack中Switch相关的内容&#xff0c;本章回中 主要介绍Card。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01; 1. 概念介绍 我们在本章回中介…

linux的shell script判断用户输入的字符串,判断主机端口开通情况

判断输入的字符串是否是hello 图一运行报错 检查发下&#xff0c;elif 判断里面少个引号&#xff0c;哎&#xff0c;现在小白到了&#xff0c;一看就会&#xff0c;一写就错的时候了&#xff0c;好像现在案例比较简单&#xff0c;行数较少。 案例二 if 结合test 判断主机端…

企业电脑屏幕监控有哪些?如何实现电脑屏幕监控

企业电脑屏幕监控有哪些&#xff1f;如何实现电脑屏幕监控 下载使用安企神电脑屏幕监控软件 企业电脑屏幕监控是一种监测和记录员工在工作时间内在他们的计算机上执行的活动的技术。这种监控可以有多种目的&#xff0c;包括确保员工的生产力、确保数据安全性&#xff0c;或满…

CCLINK IEFB总线转ETHERNET/IP网络的协议网关使欧姆龙和三菱的数据互通的简单配置方法

想要实现CCLINK IEFB总线和ETHERNET/IP网络的数据互通。 捷米JM-EIP-CCLKIE是一款ETHERNET/IP从站功能的通讯网关&#xff0c;该产品主要功能是实现CCLINK IEFB总线和ETHERNET/IP网络的数据互通。本网关连接到ETHERNET/IP总线和CCLINK IEFB总线上都可以做为从站使用。网关分别…

静态链表的定义与实现(数据结构与算法)

1. 静态链表 用数组的方式实现的链表 单链表&#xff1a; 各个结点在内存中星罗棋布、散落天涯 静态链表&#xff1a;分配一整片连续的内存空间&#xff0c; 各个结点集中安置。 1.1 静态链表的优点 不需要像动态链表那样频繁地进行内存分配和释放&#xff0c;可以节省内存…

产品手册应该如何组织内容,以便用户能够快速找到所需信息?

产品手册应该如何组织内容&#xff0c;以便用户能够快速找到所需信息&#xff1f;这是一个关乎用户体验和产品文档效力的重要问题。当用户需要了解产品的功能、操作指南或故障排除时&#xff0c;他们希望能够轻松地找到准确、清晰的信息&#xff0c;而不是在冗长的手册中迷失方…

C语言——选择排序

完整代码&#xff1a; //选择排序 // 选择排序是一种简单直观的排序算法。它的工作原理如下:首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置&#xff0c;然后&#xff0c;再从剩余未排序元素中继续寻找最小&#xff08;大&am…

Rocky 安装jdk17

1&#xff09;检测jdk是否安装&#xff1a; #运行 java -version如果提示安装&#xff0c;则输入N&#xff0c;跳过 2&#xff09;检测cpu 类型 若未安装查看linux处理器架构&#xff1a; #运行 hostnamectl #或运行 arch 3&#xff09;去官网下载相应的编译版本的Jdk Or…

[SSD综述1.7] SSD接口形态: SATA、M.2、U.2、PCIe、BGA

依公知及经验整理,原创保护,禁止转载。 专栏 《SSD入门到精通系列》 <<<< 返回总目录 <<<< 前言 犹记得当年Windows 7系统体验指数中,那5.9分磁盘分数,在其余四项的7.9分面前,似乎已经告诉我们机械硬盘注定被时代淘汰。势如破竹的SSD固态硬盘,彻…

万岳讲堂:抖音小程序开发入门指南

抖音小程序可以将开发者的创意带入这个热门的应用中。本文将带您深入了解抖音小程序的开发入门指南&#xff0c;帮助您开始在这一平台上构建自己的应用。 一、什么是抖音小程序&#xff1f; 抖音小程序是一种轻量级的应用程序&#xff0c;它可以在抖音中直接运行&#xff0c;无…

记录腾讯云重置密码之后ssh就连不上的踩坑

腾讯云轻量级服务器SSH连不上 解决方案在最后&#xff0c;点我跳转 问题背景&#xff1a; 首先ssh ubuntu用户我是能用xshell带上密钥正常连接的 其次我重置了root密码&#xff0c;自己改了一个root密码&#xff0c;因为我要用root账号使用ftp传输文件 然后重置密码之后&…

【Unity细节】生命函数Start的逻辑比从外部调用方法比起来哪个快

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…

解决vmware安装ubuntu虚拟机显示不全以及无法实现windows与虚拟机之间无法相互复制粘贴问题

01、存在问题 02、解决方案 sudo apt-get autoremove open-vm-tools sudo apt-get install open-vm-tools sudo apt-get install open-vm-tools-desktop reboot //重启在这里插入图片描述 存在Bug 如果遇到一下问题&#xff0c;请先执行下列命令&#xff0c;然后…

基于51单片机数字电压表的设计

**单片机设计介绍&#xff0c;1664【毕设课设】基于51单片机数字电压表的设计(仿真、程序、原理图、论文) 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的数字电压表是一种可以测量直流电压并将其以数字形式显示的…

【C++ 学习 ㉛】- 详解 C++11 的 lambda 表达式

目录 一、语法格式 二、函数对象和 lambda 表达式 一、语法格式 定义一个 lambda 表达式&#xff08;lambda 函数&#xff09;的语法格式如下&#xff1a; [capture-list] (parameters) mutable noexcept/throw() -> return-type { statements }; 即 [捕获列表] (参数列…

register_parameter和register_buffer 详解

在参考yolo系列代码或其他开源代码&#xff0c;经常看到register_buffer和 register_parameter的使用&#xff0c;接下来将详细对他们进行介绍。 1. 前沿 在搭建网络时&#xff0c;我们 自定义的参数&#xff0c;往往不会保存到模型权重文件中&#xff0c;或者成为模型可学习…

【多线程】并发问题

public class BuyTicket implements Runnable{private int ticketNums10;Overridepublic void run() {for(int i1;i<ticketNums;i){if(ticketNums<0){break;}System.out.println(Thread.currentThread().getName() "抢到了第" i "张票");ticketNu…

数字处理-第10届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第3讲。 数字处理&#xff…

高性能网络编程 - 关于单台服务器并发TCP连接数理论值的讨论

文章目录 概述操作系统的限制因素文件句柄限制1. 进程限制2. 全局限制 端口号范围限制 概述 单台服务器可以支持的并发TCP连接数取决于多个因素&#xff0c;包括硬件性能、操作系统限制、网络带宽和应用程序设计。以下是一些影响并发TCP连接数的因素&#xff1a; 服务器硬件性…

软件设计模式原则(二)开闭原则

继续讲解第二个重要的设计模式原则——开闭原则~ 一.定义 开闭原则&#xff0c;在面向对象编程领域中&#xff0c;规定“软件中的对象&#xff08;类&#xff0c;模块&#xff0c;函数等等&#xff09;应该对于扩展是开放的&#xff0c;但是对于修改是封闭的”&#xff0c;这意…