尚硅谷2020最新版宋红康JVM教程-中篇-第4章:再谈类的加载器-05-双亲委派模型

Java——打破双亲委派机制 文章目录打破双亲委派的原因Demo 打破双亲委派的原因 双亲委派的机制,是AppClassLoader先委托给ExtClassLoader类加载器进行加载,ExtClassLoader加载不了,则交由BootstrapClassLoader进行加载操作; 如果BootstrapClassLoader依旧加载不了,则才反向委托,直至AppClassLoader加载完成。 这样能保证,像java.lang.Object这些核心的类不被外界自定义加载,保证使用到的类库为官方定义的库,保证程序执行的安全性。 [问: 阅读详情

定义与本质

类加载器用来把类加载到Java虚拟机中。从JDK1.2版本开始,类的加载过程采用双亲委派机制,这种机制能更好地保证Java平台的安全。

定义

如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就成功返回。只有父类加载器无法完成此加载任务时,才自己去加载。

本质

规定了类加载的顺序是:引导类加载器先加载,若加载不到,由扩展类加载器加载,若还加载不到,才会由系统类加载器或自定义的类加载器进行加载。

在这里插入图片描述
在这里插入图片描述

优势与劣势

优势

  • 避免类的重复加载,确保一个类的全局唯一性
    • Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。
  • 保护程序安全,防止核心API被随意篡改

代码支持

  • 双亲委派机制在java.lang.ClassLoader.loadClass(String,boolean)接口中体现。该接口的逻辑如下:
    • 先在当前加载器的缓存中查找有无目标类,如果有,直接返回。
    • 判断当前加载器的父加载器是否为空,如果不为空,则调用parent.loadClass(name,false)接口进行加载。
    • 反之,如果当前加载器的父类加载器为空,则调用findBootstrapClassorNull(name)接口,让引导类加载器进行加载。
    • 如果通过以上3条路径都没能成功加载,则调用findClass(name)接口进行加载。该接口最终会调用java.lang.ClassLoader接口的defineClass系列的native接口加载目标Java类。

双亲委派的模型就隐藏在这第2和第3步中。

举列

假设当前加载的是java.lang.Object这个类,很显然,该类属于JDK中核心得不能再核心的一个类,因此一定只能由引导类加载器进行加载。当]VM准备加载javaJang.Object时,JVM默认会使用系统类加载器去加载,按照上面4步加载的逻辑,在第1步从系统类的缓存中肯定查找不到该类,于是进入第2步。由于从系统类加载器的父加载器是扩展类加载器,于是扩展类加载器继续从第1步开始重复。由于扩展类加载器的缓存中也一定查找不到该类,因此进入第2步。扩展类的父加载器是null,因此系统调用findClass(String),最终通过引导类加载器进行加载。

思考

如果在自定义的类加载器中重写java.lang.ClassLoader.loadClass(String)或java.lang.ClassLoader.loadclass(String,boolean)方法,抹去其中的双亲委派机制,仅保留上面这4步中的第l步与第4步,那么是不是就能够加载核心类库了呢?
这也不行!因为JDK还为核心类库提供了一层保护机制。不管是自定义的类加载器,还是系统类加载器抑或扩展类加载器,最终都必须调用 java.lang.ClassLoader.defineclass(String,byte[],int,int,ProtectionDomain)方法,而该方法会执行preDefineClass()接口,该接口中提供了对JDK核心类库的保护。

可以删除双亲委派机制,但核心仍受preDefineClass方法的保护

弊端

  • 检查类是否加载的委托过程是单向的,这个方式虽然从结构上说比较清晰,使各个ClassLoader的职责非常明确,但是同时会带来一个问题,即顶层的ClassLoader无法访问底层的ClassLoader所加载的类。
  • 通常情况下,启动类加载器中的类为系统核心类,包括一些重要的系统接口,而在应用类加载器中,为应用类。按照这种模式,应用类访问系统类自然是没有问题,但是系统类访问应用类就会出现问题。比如在系统类中提供了一个接口,该接口需要在应用类中得以实现,该接口还绑定一个工厂方法,用于创建该接口的实例,而接口和工厂方法都在启动类加载器中。这时,就会出现该工厂方法无法创建由应用类加载器加载的应用实例的问题。

结论

由于Java虚拟机规范并没有明确要求类加载器的加载机制一定要使用双亲委派模型,只是建议采用这种方式而已。比如在Tomcat中,类加载器所采用的加载机制就和传统的双亲委派模型有一定区别,当缺省的类加载器接收到一个类的加载任务时,首先会由它自行加载,当它加载失败时,才会将类的加载任务委派给它的超类加载器去执行,这同时也是Serylet规范推荐的一种做法。

破坏双亲委派机制(重点在2)

  • 双亲委派模型并不是一个具有强制性约束的模型,而是Java设计者推荐给开发者们的类加载器实现方式。
  • 在Java的世界中大部分的类加载器都遵循这个模型,但也有例外的情况,直到Java模块化出现为止,双亲委派模型主要出现过3次较大规模“被破坏”的情况。

破坏双亲委派机制1

双亲委派模型的第一次“被破坏”其实发生在双亲委派模型出现之前一—即JDKl.2面世以前的“远古”时代。
由于双亲委派模型在JDK 1.2之后才被引入,但是类加载器的概念和抽象类java.lang.ClassLoader则在Java的第一个版本中就已经存在,面对经存在的用户自定义类加载器的代码,Java设计者们引入双亲委派模型时不得不做出一些妥协,为了兼容这些已有代码,无法再以技术手段避免loadClass()被子类覆盖的可能性,只能在JDK1.2之后的java.lang.ClassLoader中添加一个新的protected方法findClass(),并引导用户编写的类加载逻辑时尽可能去重写这个方法,而不是在loadClass()中编写代码。上节我们已经分析过loadClass()方法,双亲委派的具体逻辑就实现在这里面,按照loadClass()方法的逻辑,如果父类加载失败,会自动调用自己的findClass()方法来完成加载,这样既不影响用户按照自己的意愿去加载类,又可以保证新写出来的类加载器是符合双亲委派规则的。

破坏双亲委派机制2

  • 第二次破坏双亲委派机制:线程上下文类加载器
  • 双亲委派模型的第二次“被破坏”是由这个模型自身的缺陷导致的,双亲委派很好地解决了各个类加载器协作时基础类型的一致性问题(越基础的类由越上层的加载器进行加载),基础类型之所以被称为“基础”,是因为它们总是作为被用户代码继承、调用的API存在,但程序设计往往没有绝对不变的完美规则,如果有基础类型又要调用回用户的代码,那该怎么办呢?

这并非是不可能出现的事情,一个典型的例子便是JNDI服务,JNDI现在已经是Java的标准服务,它的代码由启动类加载器来完成加载(在JDK l.3时加入到rt.jar的),肯定属于Java中很基础的类型了。但JNDI存在的目的就是对资源进行查找和集中管理,它需要调用由其他厂商实现并部署在应用程序的ClassPath下的JNDI服务提供者接口(Service Provider Interface,SPI)的代码,现在问题来了,启动类加载器是绝不可能认识、加载这些代码的,那该怎么办?(SPI:在Java平台中,通常把核心类rt.jar中提供外部服务、可由应用层自行实现的接口称为SPI)

为了解决这个困境,Java的设计团队只好引入了一个不太优雅的设计:线程上下文类加载器(Thread Context ClassLoader)。这个类加载器可以通过java.lang.Thread类的setContextClassLoader()方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那这个类加载器默认就是应用程序类加载器。

有了线程上下文类加载器,程序就可以做一些“舞弊”的事情了。JNDI服务使用这个线程上下文类加载器去加载所需的SPI服务代码,**这是一种父类加载器去请求子类加载器完成类加载的行为,这种行为实际上是打通了双亲委派模型的层次结构来逆向使用类加载器,已经违背了双亲委派模型的一般性原则,**但也是无可奈何的事情。Java中涉及SPI的加载基本上都采用这种方式来完成,例如JNDI、JDBC、JCE、JAXB和JBI等。不过,当SPI的服务提供者多于一个的时候,代码就只能根据具体提供者的类型来硬编码判断,为了消除这种极不优雅的实现方式,在JDK6时,JDK提供了java.util.ServiceLoader类,以META-INF/services中的配置信息,辅以责任链模式,这才算是给SPI的加载提供了一种相对合理的解决方案。
在这里插入图片描述

默认上下文加载器就是应用类加载器,这样以上下文加载器为中介,使得启动类加载器中的代码也可以访问应用类加载器中的类。

破坏双亲委派机制3

  • 双亲委派模型的第三次“被破坏”是由于用户对程序动态性的追求而导致的。如:代码热替换(Hot Swap)、模块热部署(Hot Deployment)等
  • IBM公司主导的JSR-291(即OSGiR4.2)实现模块化热部署的关键是它自定义的类加载器机制的实现,每一个程序模块(osGi中称为Bundle)都有一个自己的类加载器,当需要更换一个Bundle时,就把Bund1e连同类加载器一起换掉以实现代码的热替换。在oSGi环境下,类加载器不再双亲委派模型推荐的树状结构,而是进一步发展为更加复杂的网状结构。
  • 当收到类加载请求时,OSGi将按照下面的顺序进行类搜索:
    • *将以java.开头的类,委派给父类加载器加载。
    • 否则,将委派列表名单内的类,委派给父类加载器加载。
    • 否则,将Import列表中的类,委派给Export这个类的Bundle的类加载器加载。
    • 否则,查找当前Bundle的ClassPath,使用自己的类加载器加载。
    • 否则,查找类是否在自己的Fragment Bundle中,如果在,则委派给Fragment Bundle的类加载器加载。
    • 否则,查找Dynamic Import列表的Bundle,委派给对应Bund1e的类加载器加载。
    • 否则,类查找失败。

说明:只有开头两点仍然符合双亲委派模型的原则,其余的类查找都是在平级的类加载器中进行的

  • 小结:这里,我们使用了“被破坏”这个词来形容上述不符合双亲委派模型原则的行为,但这里“被破坏”并不一定是带有贬义的。只要有明确的目的和充分的理由,突破旧有原则无疑是一种创新。
  • 正如:OSGi中的类加载器的设计不符合传统的双亲委派的类加载器架构,且业界对其为了实现热部署而带来的额外的高复杂度还存在不少争议,但对这方面有了解的技术人员基本还是能达成一个共识,认为OSGi中对类加载器的运用是值得学习的,完全弄懂了OSGi的实现,就算是掌握了类加载器的精粹。

热替换的实现

  • 热替换是指在程序的运行过程中,不停止服,只通过替换程序文件来修改程序的行为。热替换的关键需求在于服务不能中断,修改必须立即表现正在运行的系统之中。基本上大部分脚本语言都是天生支持热替换的,比如:PHP,只要替换了PHP源文件,这种改动就会立即生效,而无需重启Web服务器。
  • 但对Java来说,热替换并非天生就支持,如果一个类已经加载到系统中,通过修改类文件,并无法让系统再来加载并重定义这个类。因此,在Java中实现这一功能的一个可行的方法就是灵活运用ClassLoader。
  • 注意:由不同ClassLoader加载的同名类属于不同的类型,不能相互转换和兼容。即两个不同的ClassLoader加载同一个类,在虚拟机内部,会认为这2个类是完全不同的。
  • 根据这个特点,可以用来模拟热替换的实现,基本思路如下图所示:
    在这里插入图片描述

代码举列

package T1;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {
    private String rootDir;

    public MyClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    // 编写findclass方法的逻辑
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //获取类的cLass文件字节数组
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        } else {
            //直接生成cLass对象
            return defineClass(name, classData, 0, classData.length);
        }
    }


    // 编写获cLass文件并转换为字节码流的逻辑
    private byte[] getClassData(String className) {
        //读取类文件的字节
        String path = classNameToPath(className);
        try {
            InputStream ins = new FileInputStream(path);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;

            //读取类文件的字节码
            while ((len = ins.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;

    }

    // 类文件的完全路径
    private String classNameToPath(String className) {
        return rootDir + "\\" + className.replace('.', '\\') + ".class";
    }
}

package T1;

import java.lang.reflect.Method;

public class LoopRun {
    public static void main(String[] args) {
        while (true) {
            try {
                // 1 创建自定义类加载器的实列
                MyClassLoader loader = new MyClassLoader("D:\\apache-maven-3.6.3\\maven_repo\\jvm\\jvm1\\src\\main\\webapp\\java");

                // 2 加载指定的类
                Class<?> loaderClass = loader.findClass("T1.Demo1");

                // 3 创建运行时类的实列
                Object demo1 = loaderClass.newInstance();

                // 4 获取运行时的方法
                Method hot = loaderClass.getMethod("hot");

                // 5 调用指定的方法
                hot.invoke(demo1);


                for (int i = 0; i < 10; i++) {
                    System.out.println("目前loader的地址:" + loader);
                    hot.invoke(demo1);
                }

                Thread.sleep(5000);

            } catch (Exception e) {
                System.out.println("not found");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

}

package T1;

public class Demo1 {
    public void hot(){
        System.out.println("old1------------>new2");
    }
}

candence layout快捷键 摁住鼠标左键再框选:选中 摁住鼠标右键再框选:放大 选中之后,滚动鼠标滚轮进行放大缩小。 F:回到全局 shift+V:缩小 键盘的箭头:移动视图 F1:显示帮助文档Candence help F2:保存 点击r,画出矩形时不双击鼠标,点击F3,可以设置尺寸。 Creat-Shape-Path Creat-Wiring-Bus:画多根线。F3设置线宽、间距等。 选中金属后,Shift+G画保护环guard ring。F3可以设置距离金属的间距、保护环的形状。 Path和Rectang 阅读详情

相关推荐

Spring Boot整合AWS S3文件上传实战:从配置到权限管理全流程解析

本文详细解析了Spring Boot整合AWS S3文件上传的全流程,包括基础配置、核心上传功能实现、高级权限控制及安全最佳实践。通过实战案例展示如何高效处理文件上传、大文件分片及权限管理,帮助开发者构建健壮的文件管理系统。特别强调AWS S3的高可用性和安全性,适用于企业级应用开发。

sam99的博客 283

打破双亲委派的几种方式

前言:打破双亲委派有几种方式,先了解一下什么是双亲委派,好端端为什么要打破双亲委派 双亲委派:如果一个类加载器收到加载某个类的加载请求,则该类加载器不会去加载该类,而是把这个请求给父类加载器,每个一个层次的加载器都是如此,因此所有的类加载请求最终都会传到顶端的启动类加载器,只有到父类加载器在其范围找不到该类时,会将结果返回给子类加载器,最终会找到可以加载该类的子类加载器。 双亲委派的作用:保证JDK的核心类优先加载 双亲委派模型要求如果一个类可以委派给最基础的classloader加载,就不能让高层的c

Wangxichuan_Jack的博客 1万+

Docker Desktop 在 Windows 上的安装和使用

WSL 指 “”,这是一个在 Windows 10\11 上能够运行原生 Linux 二进制可执行文件(ELF格式)的兼容层。它是由微软与Canonical公司合作开发的,旨在使纯正的Ubuntu、Debian等映像能下载和解压到用户的本地计算机,并且映像内的工具和实用工具能在此子系统上原生运行。这极大地拓展了Windows系统的功能,使用户能够在Windows环境中享受到Linux的强大功能。//Linux容器。

swadian2008的博客 6万+

JVM第一讲 JVM双亲委派机制以及打破双亲委派

JVM第一讲 JVM双亲委派机制以及打破双亲委派

程序员路同学 3520

保姆级教程:在Win10/Win11上搞定AppScan 10.0.0安装与许可证激活(含常见报错解决)

本文提供AppScan 10.0.0在Win10/Win11上的详细安装与许可证激活指南,涵盖环境准备、分步安装、文件替换技巧及常见报错解决方案。通过专业的安全测试工具部署实践,帮助用户高效完成安装并避免常见陷阱,提升Web应用安全扫描效率。

weixin_30800987的博客 424

山东大学软件工程应用与实践——GMSSL开源库(六)——SM9密钥交换协议

2021SC@SDUSC 文章目录基本概念符号及辅助算法SM9密钥交换协议 基本概念 1976年,Diffie和Hellman在其题为《密码学的新方向》的论文中首次给出了公钥密码学的定义,并提出了Diffie-Hellman密钥交换算法。该算法解决了对称密码体制中的密钥分发问题,使得通信双方可以通过公开信道安全地交换共享密钥。 使用SM9通信的双方通过对方的标识和自身的私钥,经过两次或者可选的三次信息传递过程,计算获取一个由双方共同决定的共享秘密密钥。该密钥可以作为对称密码算法的会话密钥,其中可选步骤用来实

m0_51588039的博客 1986

【JVM基础篇】打破双亲委派机制

本文探讨了Java中双亲委派机制的细节与例外情况,重点解析了三种打破该机制的方式:自定义类加载器重写`loadClass`方法、利用线程上下文类加载器和Osgi框架的类加载机制。以Tomcat为例,展示了如何通过自定义类加载器实现Web应用间类的隔离。同时,文章分析了JDBC中DriverManager如何利用SPI机制和线程上下文类加载器加载驱动,解释了这并不算真正打破双亲委派机制。最后,提到了Osgi框架的历史作用及其热部署能力,并简述了使用Arthas工具在不重启服务情况下更新字节码的热部署流程。。

我只管埋头前行,剩下的交给时间。 3162

TC3XX - MCAL知识点(三十三):基于EB Tresos配置Tc3xx的MCAL代码如何产生中心对称的三相六路发波波形

本文用于记录如何在英飞凌 tc3xx 芯片的应用开发中,借助 EB Tresos 配置工具生成的配置代码与 MCAL 源码相结合,进而实现三相六路中心对称互补的 PWM 输出效果。外部资源需求:EB Tresos23.0以上、Tasking\Hightec编译器、示波器\逻辑分析仪。

梦想技术家 1206

打破双亲委派的几种办法

源码最后有一个有意思的点是:重新开启一个线程执行Main方法启动Springboot,个人理解是之前的初始化线程中有太多的中间过程对象,exit掉本线程防止。源码就不仔细写了,大概流程是pandora通过不同的类加载器打破双亲委派,通过加载全类名@不同classloader名产生不同的类来解决问题。第一,获取线程上下文类加载器,从而也就获得了应用程序类加载器(也可能是自定义的类加载器)第三,通过线程上下文类加载器去加载这个Driver类,从而避开了双亲委派模型的弊端。使用了线程上下文加载器。

qq_38158422的博客 1637

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

算法大师! 789

【2026年得物春招算法岗- 4月18日 -第二题- 老张爬山】(题目+思路+Java&C++&Python解析+在线测试)

这篇文章介绍了一个动态规划问题,解决老张在n天内安排爬山计划以最大化愉悦值的问题。题目允许最多k次打破"不能连续两天爬山"的规则限制。 摘要要点: 使用三维动态规划数组dp[i][j][s],表示第i天结束时已用j次机会、当天状态为s(0不爬/1爬)时的最大愉悦值 状态转移考虑两种情况:当天不爬山时取前一天两种状态的最大值;当天爬山时分别处理前一天不爬山和爬山(需消耗机会)的情况 最终结果为考虑所有可能用掉的k次机会后,最后一天两种状态的最大值 提供了Python、Java和C++三种实

m0_73659489的博客 1357

尚硅谷2020最新版宋红康JVM教程-目录

第一篇:内存与垃圾回收篇 最新版宋红康JVM教程-1-JVM简介 尚硅谷2020最新版宋红康JVM教程-2-类加载子系统 尚硅谷2020最新版宋红康JVM教程-3-运行时数据区概述及线程 尚硅谷2020最新版宋红康JVM教程-4-程序计数器 尚硅谷2020最新版宋红康JVM教程-5-虚拟机栈 尚硅谷2020最新版宋红康JVM教程-6-本地方法接口 尚硅谷2020最新版宋红康JVM教程-7-本地方法栈 尚硅谷2020最新版宋红康JVM教程-8-堆 尚硅谷2020

admin741admin的博客 2689

SAP Business Technology Platform 支持的技术栈

SAP Business Technology Platform(简称 BTP)是 SAP 提供的一个综合技术平台,旨在帮助企业实现业务转型和创新。BTP 融合了数据库管理、应用开发、集成、分析和智能技术,为企业提供从基础架构到端到端应用的全面服务。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1566

jvm打破类双亲委派机制

当两个类的全限定名相同时,就不可以同时加载,入tomcat运行两个web服务时就会出现冲突(相同类名),不够tomcat通过为每一个应用分配一个应用类加载器,打破双亲委派机制。自定义实现(1)类继承ClassLoader类,重写loadClass方法(2)loadClass中获取被加载类数据(loadClassData)(3)调用defineClass完成类加载。

weixin_70202553的博客 2232

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

阿里二面:双亲委派机制?原理?能打破吗?

双亲委派机制(Parent Delegation Mechanism)是Java中的一种类加载机制。在Java中,类加载器负责加载类的字节码并创建对应的Class对象。双亲委派机制是指当一个类加载器收到类加载请求时,它会先将该请求委派给它的父类加载器去尝试加载。只有当父类加载器无法加载该类时,子类加载器才会尝试加载。这种机制的设计目的是为了保证类的加载是有序的,避免重复加载同一个类。

周沐子 8174

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【JVM】打破双亲委派机制

启动类加载器加载DriverManager在初始化DriverManager时,通过SPI机制加载Jar包中的mysql驱动SPI中利用线程上下文类加载器(应用程序类加载器) 去加载并创建对象。类加载器(ClassLoader)负责在类加载过程中的字节码获取并加载到内存这一部分。通过加载字节码数据放入内存转换成byte[],接下来调用虚拟机底层方法将byte[]转换成方法区和堆中的数据每个Java实现的类加载器中保存了一个成员变量叫“父”(Parent)类加载器。

m0_62645012的博客 3009

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

JVM问题(一) -- 如何打破双亲委派模型

1. 如何打破双亲委派模型 我们知道类的加载方式默认是双亲委派,如果我们有一个类想要通过自定义的类加载器来加载这个类,而不是通过系统默认的类加载器,说白了就是不走双亲委派那一套。即: 自定义类加载器 ,重写loadclass方法。典型的打破双亲委派模型的框架和中间件有tomcat与osgi SPI机制绕开loadclass 方法。当前线程设定关联类加载器 当然这里要注意一下,Object.class这是对象的顶级类,改变类的类加载器的时候要注意,如果全部改了,Object.class就找不到了,加载不了

weixin_39724194的博客 5668

【JVM基础(五)】双亲委派机制

介绍了什么是双亲委派机制以及如何打破双亲委派机制。

shybiubiuccy的博客 1896

JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)

⚫ 一个Tomcat程序中是可以运行多个Web应用的,如果这两个应用中出现了相同限定名的类,比如Servlet类,Tomcat要保证这两个类都能加载并且它们应该是不同的类。⚫ 如果不打破双亲委派机制,当应用类加载器加载Web应用1中的MyServlet之后,Web应用2中相同限定名的MyServlet类就无法被加载了。⚫ Tomcat使用了自定义类加载器来实现应用之间类的隔离。每一个应用会有一个独立的类加载器加载对应的类。

qq_59708493的博客 720

4、类加载及双亲委派及如何打破双亲委派

一、概述 1、JVM内存结构 二、类加载器 1、介绍 2、类加载器ClassLoader角色 3、类加载器分类 4、引导、扩展、系统【类加载器】 5、用户自定义类加载器 6、ClassLoader 7、双亲委派机制 8、沙箱安全机制 9、其他 三、类的加载过程 1、加载过程 2、Loaing(加载) 3、Linking(链接) 4、Initialization(初始化)

爱欧米 1069

JVM工作原理与实战(十二):打破双亲委派机制-自定义类加载器

JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了打破双亲委派机制的方法、自定义类加载器等内容。

Rye的博客 2334

【有料】面试必备:什么时候要打破双亲委派机制?什么是双亲委派? (图解+秒懂+史上最全)

当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。

daobuxinzi的博客 3845

JVM工作原理与实战(十三):打破双亲委派机制-线程上下文类加载器

JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了打破双亲委派机制的方法、线程上下文类加载器等内容。

Rye的博客 2074

如何打破双亲委派模型?打破双亲委派模型示例?什么是双亲委派模型?

双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。3.双亲委派就是类加载器之间的层级关系,加载类的过程是一个递归调用的过程,首先一层一层向上委托父类加载器加载,直到到达最顶层启动类加载器,启动类加载器无法加载时,再一层一层向下委托给子类加载器加载。为什么要打破双亲委派模型?

mischen520的博客 1331

【Java】双亲委派机制及其打破的相关知识笔记

在java.lang.ClassLoader的loadClass()方法中,先检查是否已经被加载过,若没有加载则调用父类加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。一句话总结就是:一个类加载器拿到一个类后不会先去加载,而是先交由父加载器加载,由是递归,直到最顶层,当父加载器无法加载时才会委派给子加载器去加载,由是递归。4.加载类或资源:在设置了线程上下文类加载器之后,通过当前线程的上下文类加载器来加载类或资源,从而实现特定线程范围内的自定义类加载逻辑。

uuzeray的博客 1515

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

双亲委派机制指的是:当一个类加载器接收到加载类的任务时,会自底向上查找是否加载过,再由顶向下进行加载。假设在com.practice包下有一个类A.java,应用程序类加载器接收到一个任务,他要去加载A.java这个类,首先他会检查一下这个类有没有被加载过,发现没有被加载过,那么他就会把这个类委派给它的父类(扩展类加载器),扩展类加载器发现也没有加载过,继续向上委派,委派给它的父亲(启动类加载器),启动类加载器发现A.java曾经加载过,所以它直接把A.java类的class对象返回,加载过程结束。

宁可枝头抱香死,何曾吹落北风中。 635
上一篇: 尚硅谷2020最新版宋红康JVM教程-中篇-第4章:再谈类的加载器-04-ClassLoader源码解析
下一篇: 尚硅谷2020最新版宋红康JVM教程-中篇-第4章:再谈类的加载器-06-08
zgcadmin
博客等级 码龄9年 174粉丝 109原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值