类加载器 & 打破双亲委派机制(个人总结)

2023-11-05

    声明: 1. 本文为我的个人复习总结, 并那种从零基础开始普及知识 内容详细全面, 言辞官方的文章
              2. 由于是个人总结, 所以用最精简的话语来写文章
              3. 若有错误不当之处, 请指出

类加载器:

  1. 启动类加载器 加载JAVA_HOME/lib下的核心类
  2. 扩展类加载器 加载JAVA_HOME/lib/ext下的扩展类
  3. 系统类加载器 加载classpath下 我们自己编写的类
  4. 自定义加载器 用户自定义路径

以上加载器的父子关系, 并非指的是extend继承, 而是逻辑上的上下级关系

双亲委派机制:

加载一个类的过程:

系统类加载器遇到一个class, 先看看扩展类加载器里有没有这个同全类名的class

如果父类有,便让父类加载器去加载;如果没有,便继续上抛,直至抛到启动类加载器为止

如果启动类也没有,那就下抛,直至能加载为止

注意: 类加载器间的上下级关系, 和它们各自能加载哪些类

优点:

保证了jdk类库的安全问题,自带的类不会被用户自己编写的同名类进行覆盖
而且促使 核心类优先加载

缺点:

  1. 父类级加载器想要加载一些class,而这个class所处位置只有子类加载器才能加载

    这个问题出现在JDBC中, 启动类加载器加载了JDK自带的DriverManager后, DriverManager用到了MySQL厂商的Driver实现。JVM规定某一类加载器加载A类时发现A用到了B,那么它就得先去加载B。所以启动类加载器就也想加载MySQLDriver, 但这个MySQLDriver实现类不在JAVA_HOME/lib下。所以要打破双亲委派,让父类加载器去使用子类加载器加载原本父类够不到的class文件

  2. 同一个类加载器, (不管是不是同一个类加载器实例) 都只能加载一个全类名相同的class, 不能区分版本
    在这里插入图片描述

    这个问题出现在Tomcat中, Tomcat自定义如上图的多个有上下级关系的自定义加载器。
    Tomcat可以运行多个webapp, 而它们可能需要使用不同版本的jar(class); 当第一个webapp要用WebAppClassLoader想加载jar-version1.0后, 抛给了父类的CommonClassLoader去加载, 于是它加载了jar-version1.0;
    那么等到第一个webapp要用WebAppClassLoader想加载jar-version2.0时, 直接去CommonClassLoader中去取了, 直接得到了jar-version1.0, 而jar-version2.0就不会再被加载。所以要打破双亲委派,让其不向上抛掷

什么时候需要打破双亲委派机制?

即面临上述的缺点的时候:

  1. 父类加载器想要使用子类加载器加载原本父类够不到的class文件时
  2. 想要同时加载同一个class的不同版本时

如何打破双亲委派机制?

  1. 使用当前线程上下文加载器(当前线程上下文加载器默认是应用类加载器) (JDBC用的是这种)
  2. 使用自定义类加载器, 重写loadclass方法, 不去父类中检查 (Tomcat用的是这种)

自定义类加载器也可以不打破双亲委派,主要是看你是否重写loadclass方法搞事情

什么时候需要自定义类加载器?

  1. 想加载不在classpath路径下的class文件
  2. 想要加载一个相同全类名但不同版本的class文件, 使之共存
  3. 热部署时, 只需要GC回收掉之前的老的类, 然后重新创建自定义类加载器实例进行加载这个新的class文件

Tomcat自定义类加载的好处:

  1. 实现了父类Common加载器加载的class, 子类加载器就不用重复加载了
  2. 可以同时使用不同版本的jar(重写loadclass打破双亲委派机制)
  3. JSP类加载器对JSP的热部署

怎么自定义类加载器?

class MyClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String classFilePath) throws ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream( );
        try {
            Files.copy(Paths.get(classFilePath), baos);
            byte[] bytes = baos.toByteArray( );
            String className = classFilePath.split("/")[2].replace(".class", "");
            return defineClass(className, bytes, 0, bytes.length);
        } catch (IOException e) {
            e.printStackTrace( );
            throw new ClassNotFoundException("class文件找不到");
        }
    }
}

// 使用
MyClassLoader myClassLoader1 = new MyClassLoader( );
MyClassLoader myClassLoader2 = new MyClassLoader( );

Class<?> userClzVersion1 = myClassLoader1.loadClass("C:/version1/com.hellosrc.User.class");
Class<?> userClzVersion2 = myClassLoader2.loadClass("C:/version1/com.hellosrc.User.class");

// 不打破双亲委派机制
// 虽然打印结果为false, 但实际上User类只被加载了一次, 
// 因为myClassLoader1和myClassLoader2 本质都是用共同的父类加载器(即系统类加载器)去加载
System.out.println(userClzVersion1 == userClzVersion2);

// 触发静态代码块, 发现只被执行了一次, 再次印证了不打破双亲委派机制时, 不能把一个全类名相同的类重复加载
Object userVersion2 = userClzVersion1.newInstance( );
Object userVersion1 = userClzVersion1.newInstance( );

HelloWorld.class可以被JVM加载多次吗?

可以,就像Tomcat那样打破双亲委派机制后,用不同的类加载器去加载HelloWorld.class,而且还可以加载不同版本

SPI服务发现机制

如在Dubbo或JDBC或Spring中, 在类路径下放的META-INF/services/文件的内容会被程序读取, 这文件里写的就是要加载的注册的服务名;

JDBC因此可以不用显示写出Class.forName(“驱动名”), 就可以直接注册驱动

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

类加载器 & 打破双亲委派机制(个人总结) 的相关文章

  • java.library.path 中没有字体管理器

    以下代码在我的桌面上运行得很好 BufferedImage image new BufferedImage width height BufferedImage TYPE INT RGB Graphics g image getGraphi
  • 在 HP Load Runner 的 VuGen 中加载 javai.dll 时出现错误

    当我尝试在 HP load runner 的 VuGen 中编译一个简单的脚本时 无法启动 JVM 并出现以下错误 Java VM Internal Error Getting Error Loading javai dll 我在用着 HP
  • 监控 Java 应用程序上的锁争用

    我正在尝试创建一个小基准 在 Groovy 中 以显示几个同步方法上的高线程争用 当监控自愿上下文切换时 应该会出现高争用 在 Linux 中 这可以通过 pidstat 来实现 程序如下 class Res private int n s
  • 强制jvm返回本机内存[重复]

    这个问题在这里已经有答案了 我时不时地运行需要大量内存的 eclipse 任务 因此 当任务运行时 jvm 会消耗大约 2 3GB 的 RAM 这是可以的 但是一旦 jvm 占用了该内存 它就不会释放它 并且我遇到了一种情况 堆中已用内存约
  • 当目标是属性时,@Throws 不起作用

    在看的同时这个问题 https stackoverflow com q 47737288 7366707 我注意到申请 Throws to a get or setuse site 没有影响 此外 唯一有效的目标 for Throws ar
  • 如何在Java中计算对象的数字年龄[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道Java中对象的年龄 当我们使用new关键字时 Java中用户定义的对象被创建 但是什么时候它会被销毁 是跨越JVM的perm
  • Java 中清除嵌套 Map 的好方法

    public class MyCache AbstractMap
  • 抛出 Java 异常时是否会生成堆栈跟踪?

    这是假设我们不调用 printstacktrace 方法 只是抛出和捕获 我们正在考虑这样做是为了解决一些性能瓶颈 不 堆栈跟踪是在构造异常对象时生成的 而不是在抛出异常对象时生成的 Throwable 构造函数调用 fillInStack
  • Scala 为了在 JVM 上运行做出了哪些妥协?

    Scala 是一种很棒的语言 但我想知道如果它有自己的运行时 如何改进 IE 由于 JVM 的选择 做出了哪些设计选择 我所知道的两个最重要的妥协是 类型擦除 http java sun com docs books tutorial ja
  • JVM:是否可以操作帧堆栈?

    假设我需要执行N同一线程中的任务 这些任务有时可能需要来自外部存储的一些值 我事先不知道哪个任务可能需要这样的值以及何时 获取速度要快得多M价值观是一次性的而不是相同的M值在M查询外部存储 注意我不能指望任务本身进行合作 它们只不过是 ja
  • 调整 Java 类以提高 CPU 缓存友好性

    在设计java类时 对于实现CPU缓存友好性有哪些建议 到目前为止我学到的是应该尽可能多地使用 POD 即 int 而不是整数 这样 在分配包含对象时 数据将被连续分配 例如 class Local private int data0 pr
  • ASM之前看一下maxStack指令吗?

    我正在尝试使用 ASM 库将字节代码转换为不同的格式 这可以使用 MethodVisitor 来完成 就像这个简单的测试代码一样 return new MethodVisitor ASM7 Override public void visi
  • 如何在没有 Node.JS 的情况下运行 UglifyJS2

    无论如何都要跑UglifyJS2 https github com mishoo UglifyJS2没有node js 假设我想使用 JavaScript 脚本引擎在 JVM 进程中运行它 怎么做 我看到米秀回答你了https github
  • 是否可以强制 JVM 在堆中而不是堆中创建对象?

    我读过一些文章 有时JVM会识别一些对象并尝试在堆栈中而不是堆中创建它 因为堆栈上的内存分配比堆中的内存分配便宜 堆栈上的释放是免费的 并且堆栈由以下方式有效管理 运行时 那么 堆栈中的对象分配是如何工作的 有什么方法可以强制 JVM 执行
  • 为什么java(>=7版本)不支持运行没有main方法的程序? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 class WithoutMain static System out println Without main class Sy
  • jmap - 组织和堆操作会给 jvm 带来开销吗?

    正如标题所述 需要多少开销jmap histo and jmap heap分别带到jvm 如果一个内存敏感的 Java 进程处于OutOfMemory 例如 大约 96 的堆已满 并且无法通过 full gc 清除 其中一项操作是否有可能将
  • 如何将 JVM 选项传递给 SBT 以在运行应用程序或测试用例时使用?

    我想在运行我的应用程序或通过 SBT 对应用程序进行测试时指定 JVM 选项 具体来说 我需要能够为 JVM 提供 Djava security policy 参数 以便加载我的策略并用于测试 我怎样才能用 SBT 做到这一点 With x
  • 了解 Sun JVM [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么Java编译器复制finally会阻塞?

    当使用简单的代码编译以下代码时try finally块中 Java 编译器产生以下输出 在 ASM 字节码查看器中查看 Code try System out println Attempting to divide by zero Sys
  • 运行具有外部依赖项的 Scala 脚本

    我在 Users joe scala lib 下有以下 jar commons codec 1 4 jar httpclient 4 1 1 jar httpcore 4 1 jar commons logging 1 1 1 jar ht

随机推荐

  • Vue项目优化——通过 externals 加载外部 CDN 资源

    1 发现项目中存在的问题 为了直观地发现项目中存在的问题 我们可以在打包时生成报告 我们可以通过VueCli可视化的UI面板运行bulid直接查看报告 而在报告中我们发现了有这么一个文件 体积比较大 这样可能会造成我们较长时间的请求 2 那
  • JAV学习Object类

    Obj类 首先我们要认识到 Object类是我们所有类的顶层父类 所有类都是直接或者间接的继承自他 我们可以将它new出来也就是格式 Object obj new Object 我们罗列出来objct类的常用方法然后再一一介绍 方法名 ob
  • Flowable的基本使用 (4常用BPMN图配置)

    Flowable的基本使用 4常用BPMN图配置 上面几篇博客我们已经介绍了BPMN是什么 有什么节点 节点直接的关系与作用 这一篇我们画几个标准一些的BPMN图 一字长蛇阵 流程只要审核了就到下个节点 不审核就一直卡住 节点都配置了权限信
  • 媒介盒子「AI一键生成文章」功能上线,连新闻稿都不用自己写了~

    媒介盒子 AI一键生成文章 功能上线 发软文再也不用担心没有软文稿了 媒介盒子 AI一键生成文章 功能专为有软文发稿需求 但没有软文稿件的用户量身定做 媒介盒子作为国内首屈一指的专业软文发稿平台 在以往合作的客户中 经常有人反馈 我们公司没
  • python--argparse之action用法

    argparse之action用法 action关键字默认状态有两种 store true和store false 若输入命令时 不指定其参数 则store true显示为False store false显示为True 下面举个例子来直观
  • C++加密库 Crypto++

    lcrypto algorithm type name authenticated encryption schemes GCM CCM EAX high speed stream ciphers Panama Sosemanuk Sals
  • python从Excel表格中读取数据

    使用python从Excel表格中读取数据 需要安装xlrd库 pip3 install xlrd 或者 pip install xlrd 之后就可以在 py文件中导入该模块了 import xlrd
  • 用ppt图表分析人口数据

    2022年7月11日是世界人口日 联合国经济和社会事务部 经社部 在这一天发布了 世界人口展望2022 联合国每两年或三年发布一次 世界人口展望 的版本 上一个版本是2019版 世界人口展望2022 预测2022年11月15日 世界人口将达
  • 爆料称字节跳动实习生删库

    本文转载自IT之家 6 月 24 日消息 脉脉用户 程序员 白胜 在社交媒体称 字节跳动一名实习生删除了公司所有 lite 模型 在脉脉上引发关注 这名用户随后在回复中称 实习生直接 delete 父目录 还加了 skip trash li
  • 算法题记录【华为od】查找单入口空闲区域

    题目描述 思路分析 来源 华为OD真题学习 查找单入口空闲区域 100 大为童鞋的博客 CSDN博客 总体思路是遍历数组 查找符合要求的点即可 注意点一 单入口区域只能存在一个入口 用count判断是否只存在一个入口 注意点二 目标点上下左
  • 【云原生学习】PromQL学习以及Node Exporter常用查询语句

    文章目录 PromQL学习以及Node Exporter常用查询语句 一 PromQL学习 1 1 表达式数据类型 1 1 1 Instant vector selectors 1 1 2 区间vector selectors 1 2 符合
  • pythonpandas数据输出_[Python]pandas用法-数据系列,pythonpandas,使用,Series

    pandas数据Series 目录 默认数字索引 import pandas as pd import numpy as np from pandas import Series from pandas import DataFrame o
  • 软件工程知识-软件测试

    1 软件测试是发现软件错误 缺陷 的主要手段 从是否关系软件内部结构和具体实现的角度对软件测试进行分类 2 静态测试 以检查为主 桌前检查 代码走查 代码审查 动态测试 实际运行程序 分白盒测试 黑盒测试 灰盒测试 白盒测试 结构测试 用于
  • AI加速(八)

    大家好啊 我是董董灿 前文回顾 AI加速 一 GPU为什么这么牛 AI加速 二 计算机存储和计算的分离 AI加速 三 每条指令都是流水线的工人 AI加速 四 衣柜般的分层存储设计 AI加速 五 一个例子看懂流水 从指令到算法 AI加速 六
  • 18769 不完整的排序

    时间限制 1000MS 代码长度限制 10KB 提交次数 0 通过次数 0 题型 编程题 语言 不限定 Description 一个数组只包含正负整数 请使用一个O n 级别的算法对其进行排序 只需将负数全部放前面 正数全部放后面即可 无需
  • 机器学习中特征的处理及选择

    基础概念 特征工程是通过对原始数据的处理和加工 将原始数据属性通过处理转换为数据特征的过程 属性是数据本身具有的维度 特征是数据中所呈现出来的某一种重要的特性 通常是通过属性的计算 组合或转换得到的 比如主成分分析就是将大量的数据属性转换为
  • 做接口测试如何上次文件

    在日常工作中 经常有上传文件功能的测试场景 因此 本文介绍两种主流编写上传文件接口测试脚本的方法 首先 要知道文件上传的一般原理 客户端根据文件路径读取文件内容 将文件内容转换成二进制文件流的格式传输给服务端 而服务端接受客户端传过来的二进
  • 构建ubuntu根文件系统

    构建ubuntu根文件系统 象棋小子 1048272975 Ubuntu是一个广泛应用于个人电脑 云计算 以及智能物联网设备的开源操作系统 针对智能物联网 Ubuntu提供了一套更加安全 轻量级 专为智能物联网订制的开源操作系统Ubuntu
  • 前后端交互的api

    api是application interface应用接口 通过原生ajax或者jQuery或者axios 发送请求 连接后端的核心纽带 可以说也是一种革命 因为之前都是混编 html代码与后端语言杂合在一起 原码即是运行的代码 不加以修饰
  • 类加载器 & 打破双亲委派机制(个人总结)

    声明 1 本文为我的个人复习总结 并非那种从零基础开始普及知识 内容详细全面 言辞官方的文章 2 由于是个人总结 所以用最精简的话语来写文章 3 若有错误不当之处 请指出 类加载器 启动类加载器 加载JAVA HOME lib下的核心类 扩