jvm进阶之双亲委派机制(代码片段)

编程小吉 编程小吉     2022-11-28     232

关键词:

双亲委派机制

1.概述

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

2.本质

等同于规定了类加载的顺序是:引导类加载器先加载,扩展类加载器次加载,最后才会由系统类加载器加载。

3.实现

双亲委派机制在java.lang.ClassLoadelr.loadClass方法中体现,过程如下:

  1. 先在当前类加载器的缓存中查找有无目标类,如果有,直接返回。
  2. 判断当前加载器的父加载器是否为空,如果不为空,则调用parent.loadClass方法进行加载。
  3. 如果当前加载器的父类加载器为空,则调用findBootstrapClassOrNull方法,让引导类加载器进行加载。
  4. 如果以上3条路径都没能成功加载,则调用findClass方法进行加载。

4.优点

  • 避免类的重复加载,确保类的全局唯一性
  • 保护程序安全,防止核心API被随意篡改

5.弊端

检查类是否加载的委托过程是单向的,这个方式虽然从结构上说比较清晰,但使得顶层的ClassLoader无法访问底层的ClassLoader所加载的类。

6.注意细节

  • 即使我们重写java.lang.ClassLoader.loadClass方法,然后抹去其中的双亲委派机制,我们也不能覆盖JDK中的核心API类库。因为JDK还为核心类库提供了一层保护机制,不管是自定义的类加载器,还是系统类加载器等等,最终都必须调用preDefineClass方法,该方法中提供了对JDK核心类库的保护。
  • JVM规范并没有明确要求类加载器的加载机制一定要使用双亲委派模型,只是建议采用这种方式而已。 比如在Tomcat中,类加载器所采用的加载机制就和传统的双亲委派模型有一定区别,当缺省的类加载器接收到一个类的加载任务时,首先会由它自行加载,当它加载失败时,才会将类的加载任务委派给它的超类加载器去执行。

7.破坏示例

  • 双亲委派模型第一次“被破坏”发生在JDK1.2之前。

    因为双亲委派机制是在JDK1.2之后推出的,所以之前没有双亲委派机制。

  • 双亲委派模型第二次“被破坏”是由它自身存在的缺陷所导致的。

    • 在Java中,JNDI是一个标准服务,它是由启动类加载器来完成加载的,但它存在的目的是对资源进行查找和集中管理,所以它需要调用由其他厂商实现并部署在应用程序的下的JNDI服务提供者接口。

    • 如果使用双亲委派机制,那么启动类加载器根本无法调用这些实现接口方法,所以Java的设计团队设计了线程上下文类加载器,这个类加载器可以通过Thread类的setContextClassLoader方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那这个类加载器默认就是应用程序类加载器。

    • JNDI服务使用这个线程上下文类加载器去加载所需的SPI服务代码,这是一种父类加载器去请求子类加载器完成类加载的行为,这种行为实际上是打破了双亲委派模型的层次结构来逆向使用类加载器,已经违背了双亲委派模型的一般性原则。其实,Java中涉及SPI的加载基本上都采用这种方式来完成,例如JNDI、JDBC、JCE、JAXB、JBI等。

  • 双亲委派模型第三次“被破坏”是由于用户对程序动态性的追求而导致的。

    以OSGI为例,它主要是实现模块化热部署的,每一个程序模块都有一个自己的类加载器,当需要更换一个程序模块时,就把该模块连同类加载器一起换掉以实现代码的热替换。在OSGi环境下,类加载器不再使用双亲委派模型中的树状结构,而是进一步发展为更加复杂的网状结构。

8.热替换

  • 热替换是指在程序的运行过程中,不停止服务,只通过替换程序文件来修改程序的行为。热替换的关键需求在于服务不能中断,修改必须立即表现正在运行的系统之中。基本上大部分脚本语言都是天生支持热替换的,比如:PHP,只要替换了PHP源文件,这种改动就会立即生效,而无需重启Web服务器。

  • 在Java中,如果一个类已经加载到了系统中,那么通过修改类文件并无法让系统再此加载并重定义这个类,因为所有类都只会被加载一遍。

  • 不过在Java中实现这一功能的一个可行的方法就是灵活运用ClassLoader,然后自定义一个类加载器,去不断的加载此类。

    package com.example;
    
    public class Demo1 
        public void hot() 
            // 修改之前
    		System.out.println("OldDemo1");
            // 修改之后
    		System.out.println("OldDemo1---> NewDemo1");
        
    
    
    public class LoopRun 
        public static void main(String args[]) 
            while (true) 
                try 
                    // 创建自定义类加载器的实例
                    MyClassLoader loader = new MyClassLoader("ClassDir");
                    // 加载类
                    Class clazz = loader.findClass("com.example.Demo1");
                    
                    // 创建类的实例
                    Object demo = clazz.newInstance();
                    
                    // 调用类的方法
                    Method m = clazz.getMethod("hot");
                    m.invoke(demo);
                    
                    // 每隔5秒打印一次
                    Thread.sleep(5000);
                 catch (Exception e) 
                    e.printStackTrace();
                
            
        
    
    

    修改之前输出

    修改之后输出

jvm进阶之双亲委派机制(代码片段)

双亲委派机制1.概述2.本质3.实现4.优点5.弊端6.注意细节7.破坏示例8.热替换1.概述如果一个类加载器在接收到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父加载器去完成。依次递归ÿ... 查看详情

jvm----大白话图文之jvm类加载机制内存区域垃圾回收(代码片段)

...过程2.1概念2.2什么时候初始化一个类?3、类加载器和双亲委派机制3.1类加载器3.2双亲委派机制3.3Tomcat类加载机制3.3.1破坏双亲委派二、内存区域1、内存区域划分1.1存放类的方法区1.2执行代码指令用的程序计数器1.3虚拟机机栈... 查看详情

jvm类加载器:双亲委派机制沙箱安全机制(代码片段)

·双亲委派机制、沙箱安全机制是JVM中类加载器系统的相关术语·在这之前,应该先了解JVM类加载器系统的相关概念一、类加载器基础知识    见下图1,java文件首先会被编译成class文件,class文件作为Java虚拟机的可... 查看详情

双亲委派机制(代码片段)

双亲委派机制简单理解简单一句话:我爸是李刚,有事找我爸。简单三个字:往上捅双亲委派就是,有啥事,先问问老爹,如果老爹不行,再问问爷爷,如果爷爷也没有,再告爸爸,爸爸再告诉诉儿子,你自己看着办吧。图例:... 查看详情

jdbc是如何打破双亲委派模式的(代码片段)

yJDBC是如何打破双亲委派模式的-掘金为什么JDBC需要打破双亲委派机制JDBC的DriverManager与SPI机制类加载的机制以及双亲委派机制的介绍可以参考JVM类加载机制在JDBC4.0之后,我们不再需要调用Class.https://juejin.cn/post/7007292903361871903... 查看详情

jvm初探(一):双亲委派机制(代码片段)

目录一、JVM初探1.1JVM的位置1.2JVM体系结构二、双亲委派机制2.1类加载器2.2面试问题三、沙箱安全机制3.1什么是沙箱3.2组成沙箱的基本条件一、JVM初探JVM是JavaVirtualMachine(Java虚拟机)的缩写,JVM是一种用于计算机设备的规范... 查看详情

双亲委派机制(代码片段)

前言我们在IDE中编写的Java源代码被编译器编译成.class的字节码文件。然后由ClassLoader(类加载器)负责将这些.class文件加载到JVM中去执行。ClassLoaderBootstrapClassLoader(启动类加载器)C++实现在java里无法获取负责加载<JAVA_HOME>/lib... 查看详情

jvm技术专题针对于加载器与双亲委派机制分析和研究指南「入门篇」(代码片段)

任何足够先进的科技,都与魔法无异加载器与双亲委派机制类加载器是怎么被创建出来的?什么是双亲委派机制?为什么要有这种机制?Class实例和类加载器究竟是在JavaHeap中,还是在方法区中?类加载器:... 查看详情

呜,双亲委派模式伤心史(代码片段)

文章目录一、前言二、双亲委派模式2.1双亲委派模式的结构2.2先加载父类,再加载子类2.3不可以跨模块加载2.4小结三、JDBC的SPI机制违背双亲委派模式3.1为什么说JDBC破坏了双亲委派模式3.2JDBC是如何破坏JVM的双亲委派模式的3.3J... 查看详情

呜,双亲委派模式伤心史(代码片段)

文章目录一、前言二、双亲委派模式2.1双亲委派模式的结构2.2先加载父类,再加载子类2.3不可以跨模块加载2.4小结三、JDBC的SPI机制违背双亲委派模式3.1为什么说JDBC破坏了双亲委派模式3.2JDBC是如何破坏JVM的双亲委派模式的3.3J... 查看详情

jvm--双亲委派机制

要了解双亲委派机制得先了解个概念:类加载器:“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块成为... 查看详情

jvm--类加载器;双亲委派机制;线程上下文类加载器(代码片段)

一、类加载器类加载器就是根据类的二进制名(binaryname)读取java编译器编译好的字节码文件(.class文件),并且转化生成一个java.lang.Class类的一个实例。每个实例用来表示一个Java类,jvm就是用这些实例来... 查看详情

jvm--类加载器;双亲委派机制;线程上下文类加载器(代码片段)

一、类加载器类加载器就是根据类的二进制名(binaryname)读取java编译器编译好的字节码文件(.class文件),并且转化生成一个java.lang.Class类的一个实例。每个实例用来表示一个Java类,jvm就是用这些实例来... 查看详情

jvm类加载器与双亲委派模型(代码片段)

...oader类前面说到,ClassLoader这个顶级父类只是定义好了双亲委派模型的工作机制;但是ClassLoader是个抽象类,无法直接创建对象,所以需要由继承它的子类完成创建对象的任务。子类需要自己实现findClass方法,... 查看详情

从源码理解双亲委派机制,原来如此简单(代码片段)

...介绍类加载机制的几个硬核问题:1从JDK源码级别剖析双亲委派机制原理2自定义类加载器研究如何打破双亲委派机制3.理解Tomcat的沙箱安全机制目录1双亲委派机制介绍2双亲委派机制实现原理3.打破双亲委派机制4Tomcat的沙箱机... 查看详情

双亲委派机制(代码片段)

双亲委派机制双亲委派的原理:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委托给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶... 查看详情

jvm专题四:类加载子系统双亲委派机制

2.双亲委派机制 2.1双亲委派机制工作原理 2.1.1原理 Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存,生成class对象。 加载某个类的class文件时,Java虚拟机... 查看详情

jvm系列浅谈双亲委派和破坏双亲委派(代码片段)

...。前段时间,笔者同事提出了一个关于类加载器破坏双亲委派的问题& 查看详情