双亲委派机制与类加载器的自定义

类加载器的作用与位置

  

在java字节码文件交给JVM运行时,需要类加载器子系统进行加载,类加载器子系统主要分为

三个阶段加载 链接 初始化具体可以看我前两篇博客这里就不再赘述

加载阶段主要有三个加载器引导类加载器 扩展类加载器 系统类加载器完成

他们的作用就是加载class文件到内存中,具体来说是把数据结构等信息存放在方法区,生成Class模板存放在堆区

三个加载器的关系

引导类加载器由c/c++代码编写,扩展类加载器和系统类加载器由java编写都继承于ClassLoader,他们三者属于层级关系,并不是继承

  ClassLoader classLoader = son.class.getClassLoader();System.out.println(classLoader);System.out.println(classLoader.getParent());

Parent只是类的属性用于实现双亲委派并非是使用extends的继承关系

这里为类的加载器的parent字段赋值

扩展类和系统类加载器的加载

   

在 Java 虚拟机中,扩展类加载器和系统类加载器都是由启动类加载器加载的。

启动类加载器(Bootstrap Class Loader)是 Java 虚拟机的一部分,负责加载 Java 的核心类库,如 java.lang.Object 和 java.lang.String 等。启动类加载器通常是由 Java 虚拟机的实现提供,它是用本地代码实现的,不是一个普通的 Java 类。

扩展类加载器(Extension Class Loader)和系统类加载器(System Class Loader)都是普通的 Java 类,它们实际上是由启动类加载器加载的。启动类加载器在启动 Java 虚拟机时就已经存在,它会负责加载扩展类加载器和系统类加载器。这样就形成了一个层次结构,启动类加载器位于最顶层,扩展类加载器和系统类加载器位于其下。

扩展类加载器初始化过程

扩展类加载器的初始化参数ClassLoader为null这也就是为什么通过扩展类加载器获得(父类)加载器结果为null

系统类加载器初始化过程

可以看到var1就是上一步创建的扩展类加载器,这也是为什么系统类加载器的(父类)是扩展类加载器

类的加载过程

一个类加载器只会加载一次类,每个加载器会存放加载过的类的全类名,这样保证每个类只加载一次,以自定义类为例子,当使用new 关键字时,先由系统类加载器向上访问扩展类加载器,然后由扩展类加载器向上查看系统类加载器能否加载,当系统类加载器发现不能加载后就由扩展类加载器尝试加载,由于是自定义类,扩展类加载器也不能加载,接着再由系统类加载器加载。每次加载类时都是先判断上级加载器是否可以加载,如果不能再一次向下直到找到合适的类加载器。

这就是双亲委派

ClassLoader的loadClass方法

这就是上述双亲委派的实现机制

如果resolve为true就会进行解析,把符号引用转为直接引用

双亲委派机制

优势:

避免了类的重复加载

保护了java的核心API避免被篡改

劣势

  1. 灵活性受限:双亲委派机制对于自定义类加载器的灵活性有一定的限制。由于双亲委派机制会优先委派给父类加载器加载类,自定义类加载器无法覆盖或修改父类加载器加载的类。这在某些特定的场景下可能会限制了类加载的灵活性和自定义性。

  2. 安全性问题:尽管双亲委派机制可以提供一定的安全性,防止恶意类的加载,但在某些情况下也可能引发安全性问题。如果恶意代码能够伪装成一个被父类加载器加载的类,它可能会绕过子类加载器的安全检查,从而在应用程序中执行恶意操作。

  3. 类加载器冲突:在某些情况下,双亲委派机制可能会导致类加载器冲突。当多个类加载器同时加载同一个类时,由于双亲委派机制的存在,可能会导致类的多次加载或类加载器之间的冲突。这可能会引发类的不兼容性或其他运行时问题。

  4. 动态更新的困难:双亲委派机制在类加载时会优先从父类加载器中寻找已加载的类,这可能会导致动态更新的困难。即使应用程序中存在新版本的类文件,由于父类加载器已加载了旧版本的类,新版本的类可能无法被加载和使用,除非重新启动应用程序或使用特殊的技术来实现动态更新。

  5. 检查类是否加载的过程是单向的

双亲委派的破坏

第一次:

由于jdk1.2之前没有实现双亲委派机制,在1.2时引入双亲委派代码的实现但是ClassLoader是一个抽象类,如果实现的时候重写loadClass方法就会导致双亲委派的失效,所以又定义了一个finClass方法,在保持双亲委派的同时用户还能自己定义findClass方法

第二次

  主要为了解决双亲委派模型的缺陷--类的单项加载,引入了线程上下文类加载器;

这个加载器可以通过Thread类的setContextClassLoader方法进行设置,如果创建线程时未设置就继承自父线程,如果都没设置就默认是应用程序类加载器

 第三次

   主要为了解决java代码无法代码热替换,模块部署,动态更新问题。由IBM主导的OSGI实现模块化热部署的关键就是类的加载器的实现每个模块都有自己的加载器,当更新时连同模块和类的加载器一起换掉就实现了代码的热部署

类加载器的重写

一:如果要改变双亲委派就重写loadClass方法

二:使用双亲委派就重写findClass方法

public class MyClassLoad extends ClassLoader{String byteCode;public MyClassLoad(ClassLoader parent , String byteCode){super(parent);this.byteCode = byteCode;}public MyClassLoad(String byteCode){this.byteCode = byteCode;}@Overrideprotected Class findClass(String name) throws ClassNotFoundException {String url = byteCode+name+".class";Class aClass = null;BufferedInputStream ios = null;ByteArrayOutputStream ots = null;try {ios = new BufferedInputStream(new FileInputStream(url));byte[] bytes = new byte[1024];int led = 0;ots = new ByteArrayOutputStream();while ((led =ios.read(bytes)) != -1) {ots.write(bytes, 0, led);}byte[] bytes1 = ots.toByteArray();aClass = defineClass(null,bytes1, 0, bytes1.length);}catch (Exception e){e.printStackTrace();}finally {if(ios!=null) {try {ios.close();ots.close();} catch (IOException e) {throw new RuntimeException(e);}}}return aClass;}}

接下来解决代码热部署

主方法不停的加载类并创建r的实例对象,要先编译r.java的文件

public class r {public r(){System.out.println("开始");}
}

此时控制台结果

此时修改r的构造方法输出“开始zhong”

此时在使用前端编译器javac编译r.java文件( javac -encoding UTF-8 r.java解决编码问题)

这样就实现了代码的热部署

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

轻松整理文件夹,将视频文件全部归类到另一个文件夹!

如果你需要整理文件夹中的文件,将同一类别的文件归纳到一起,可以更加方便地管理和查找。现在,我们有一个简单而实用的方法,可以将文件夹中的所有视频文件归类到另一个文件夹中,让你的文件管理更加有序和高效。 首先&am…

vivado调试核ILA使用技巧

ILA(Integrated Logic Analyzer)IP Core 是 vivado 的调试核,具体如何创建、调用就不详说了。这里主要记录一个 ILA 的使用技巧,可以大大提高调试效率。 在 Program Device 后,如果添加了 ILA 核,则会出现以…

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】

一、前言 我们在使用微服务的时候,往往设计到各个微服务之间的调用,肯定会存在深度的调用链路,如果出现BUG或者异常,就会让问题定位和处理效率非常低。 有了Sleuth ,就可以帮助我们记录、跟踪应用程序中的请求和操作。…

基于springboot实现乒乓球预约管理系统项目【项目源码】计算机毕业设计

基于springboot实现乒乓球预约管理系统演示 系统的开发环境 浏览器:IE 8.1(推荐6.0以上) 开发使用语言:JAVA JDK版本:JDK_8 数据库管理系统软件:Mysql 运行平台:Windows 7 运行环境&#…

springboot2自动加载sql文件

文章目录 1. Spring Boot 2 初始化数据库脚本 data.sql & user.sql2. 文件放置的位置 如下表:3. application.yml 配置写法 1. Spring Boot 2 初始化数据库脚本 data.sql & user.sql user.sql :数据表结构 data.sql :数据内容 2. 文…

MATLAB实现灰色预测

久违了,前段时间由于学习压力大,就没怎么更新MATLAB相关的内容,今天实在学不进去了,换个内容更新一下~ 本贴介绍灰色预测模型,这也是数学建模竞赛常见算法中的一员,和许多预测模型一样——底层原理是根据已…

身份证号码校验

根据《新版外国人永久居留身份证适配性改造要点》,公司需要把代码中对身份证的校验进行优化 就文档内容可以看到需要优化的要点是: 新版永居证号码以 9 开头 受理地区代码出生日期顺序码校验码;(共18位) eg&#xff…

【算法萌新闯力扣】:两句话中的不常见单词

力扣热题:两句话中的不常见单词 开篇 今天是备战蓝桥杯的第19天,今天到目前刷了4道力扣算法题。其中,这道题是对我来说收获最大的一道,让我更熟练地掌握了一些算法题中方法,于是来与大家分享一下。 题目链接: 884.两…

猫罐头多久喂一次?放心猫罐头品牌推荐

猫罐头是猫咪喜爱的食物之一,然而,正确的喂养方法也是非常重要的。不能随意给猫咪喂食猫罐头。 作为从业6年的宠物护理师来说,只买合适的,贵的不如好的,只要配方不出错营养跟得上,观察自家猫咪体质真的基本…

算法分析-三壶谜题

一.题目需求 有一个充满水的8品脱的水壶和两个空水壶(容积分别是5品脱和3品脱)。 通过将水壶完全倒满水和将水壶的水完全倒空这两种方式,在其中的一个水壶中得到4品脱的水。 二、算法思想 1.算法分析 1.1. 采用的算法思想是将某个时刻水壶…

《向量数据库指南》——向量数据库Milvus Cloud搭建Excel公式编辑器助手

引言 在日常工作中,Excel是我们经常使用的办公工具,而熟练应用Excel公式对于提高工作效率非常重要。然而,有时候我们会遇到一些复杂的需求,需要用到较为专业的Excel公式,而这正是Excel公式编辑器助手的用武之地。本文将介绍如何利用向量数据库Milvus Cloud搭建GPT大模型和…

灾备建设中,跨主机集群恢复技术应用

在介绍跨主机集群恢复之前,要了解到虚拟化主机集群是什么? 虚拟化主机集群是一种把一组主机组合起来形成一个整体,向用户提供资源方式(计算存储、存储资源、网络资源)的技术。 虚拟化集群具有以下特性: …