【JVM】详解双亲委派机制

2024-06-18 13:04

本文主要是介绍【JVM】详解双亲委派机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

双亲委派机制是Java类加载器的一种工作模式,确保类加载的一致性和安全性。以下是详细的定义、优缺点以及如何破坏双亲委派机制的描述。

双亲委派机制的定义

双亲委派机制(Parent Delegation Model)是一种类加载器的工作模式。在这种模式下,类加载器在加载类时,会先将加载请求委派给父类加载器处理,只有当父类加载器无法完成类加载时,子类加载器才会尝试加载该类。

双亲委派机制的工作过程:
  1. 检查缓存:类加载器首先检查是否已经加载过该类,如果已经加载过,则直接返回该类。
  2. 委派父加载器:如果没有加载过该类,类加载器将加载请求委派给父类加载器。
  3. 递归过程:父类加载器也按照相同的过程处理加载请求,直到委派到启动类加载器(Bootstrap ClassLoader)。
  4. 启动类加载器加载:启动类加载器尝试加载类,如果加载成功,则返回该类,否则继续步骤5。
  5. 逐级回退:如果启动类加载器无法加载该类,加载请求逐级回退到下一级类加载器,直至回退到最初的请求者。
  6. 自行加载:最终,如果所有父类加载器都无法加载该类,子类加载器才会尝试自行加载。

双亲委派机制的优点

  1. 安全性:双亲委派机制确保了核心类库(如java.lang.*包)不会被重复加载和篡改。只有启动类加载器能加载这些核心类库,避免了安全风险。
  2. 避免类重复加载:通过委派机制,保证了类只会被加载一次,从而节省内存,提高性能。
  3. 一致性:同一个类在整个Java应用中只有一个唯一的定义,避免了同名类不同实现的冲突问题。

双亲委派机制的缺点

  1. 灵活性不足:双亲委派机制的严格层级关系使得子类加载器很难绕过父类加载器直接加载类,这在某些情况下限制了灵活性。
  2. 复杂性:实现自定义类加载器时,需要理解和实现双亲委派机制,这增加了开发的复杂性。

如何破坏双亲委派机制

破坏双亲委派机制通常是为了满足某些特定需求,如加载自定义的类或版本不同的类库。以下是一些破坏双亲委派机制的方法:

1. 自定义类加载器

通过继承ClassLoader并覆盖loadClass方法,可以实现不使用双亲委派机制的类加载器。

public class CustomClassLoader extends ClassLoader {@Overridepublic Class<?> loadClass(String name) throws ClassNotFoundException {// 不委派给父类加载器,直接加载类byte[] classData = getClassData(name);if (classData == null) {throw new ClassNotFoundException();}return defineClass(name, classData, 0, classData.length);}private byte[] getClassData(String className) {// 读取类文件的字节码String path = className.replace('.', '/') + ".class";try (InputStream is = getClass().getResourceAsStream(path)) {ByteArrayOutputStream byteStream = new ByteArrayOutputStream();int nextValue = 0;while ((nextValue = is.read()) != -1) {byteStream.write(nextValue);}return byteStream.toByteArray();} catch (IOException e) {e.printStackTrace();return null;}}
}
2. 使用不同的类加载器加载不同版本的类

通过不同的类加载器加载不同版本的类库,避免类库冲突。

public class VersionClassLoader extends ClassLoader {private String version;public VersionClassLoader(String version) {this.version = version;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {String path = "/lib/" + version + "/" + name.replace('.', '/') + ".class";try (InputStream is = getClass().getResourceAsStream(path)) {if (is == null) {throw new ClassNotFoundException(name);}ByteArrayOutputStream byteStream = new ByteArrayOutputStream();int nextValue = 0;while ((nextValue = is.read()) != -1) {byteStream.write(nextValue);}byte[] classData = byteStream.toByteArray();return defineClass(name, classData, 0, classData.length);} catch (IOException e) {throw new ClassNotFoundException(name, e);}}
}
3. 重写findClass方法

通过重写ClassLoaderfindClass方法,自定义类加载逻辑,从而绕过父类加载器。

public class CustomFindClassLoader extends ClassLoader {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {byte[] classData = getClassData(name);if (classData == null) {throw new ClassNotFoundException();}return defineClass(name, classData, 0, classData.length);}private byte[] getClassData(String className) {String path = className.replace('.', '/') + ".class";try (InputStream is = getClass().getResourceAsStream(path)) {ByteArrayOutputStream byteStream = new ByteArrayOutputStream();int nextValue = 0;while ((nextValue = is.read()) != -1) {byteStream.write(nextValue);}return byteStream.toByteArray();} catch (IOException e) {e.printStackTrace();return null;}}
}

总结

双亲委派机制通过递归委派机制确保了Java类加载的安全性、一致性和性能。但是,为了满足某些特定需求,有时需要破坏这一机制。通过自定义类加载器并覆盖loadClassfindClass方法,可以实现不依赖双亲委派机制的类加载逻辑。尽管如此,在破坏双亲委派机制时应谨慎操作,以避免潜在的类加载冲突和安全问题。

这篇关于【JVM】详解双亲委派机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

Python使用openpyxl读取Excel的操作详解

《Python使用openpyxl读取Excel的操作详解》本文介绍了使用Python的openpyxl库进行Excel文件的创建、读写、数据操作、工作簿与工作表管理,包括创建工作簿、加载工作簿、操作... 目录1 概述1.1 图示1.2 安装第三方库2 工作簿 workbook2.1 创建:Workboo

SpringBoot集成EasyPoi实现Excel模板导出成PDF文件

《SpringBoot集成EasyPoi实现Excel模板导出成PDF文件》在日常工作中,我们经常需要将数据导出成Excel表格或PDF文件,本文将介绍如何在SpringBoot项目中集成EasyPo... 目录前言摘要简介源代码解析应用场景案例优缺点分析类代码方法介绍测试用例小结前言在日常工作中,我们经

Python实现中文文本处理与分析程序的示例详解

《Python实现中文文本处理与分析程序的示例详解》在当今信息爆炸的时代,文本数据的处理与分析成为了数据科学领域的重要课题,本文将使用Python开发一款基于Python的中文文本处理与分析程序,希望... 目录一、程序概述二、主要功能解析2.1 文件操作2.2 基础分析2.3 高级分析2.4 可视化2.5

Java实现预览与打印功能详解

《Java实现预览与打印功能详解》在Java中,打印功能主要依赖java.awt.print包,该包提供了与打印相关的一些关键类,比如PrinterJob和PageFormat,它们构成... 目录Java 打印系统概述打印预览与设置使用 PageFormat 和 PrinterJob 类设置页面格式与纸张

Spring Security常见问题及解决方案

《SpringSecurity常见问题及解决方案》SpringSecurity是Spring生态的安全框架,提供认证、授权及攻击防护,支持JWT、OAuth2集成,适用于保护Spring应用,需配置... 目录Spring Security 简介Spring Security 核心概念1. ​Securit

MySQL 8 中的一个强大功能 JSON_TABLE示例详解

《MySQL8中的一个强大功能JSON_TABLE示例详解》JSON_TABLE是MySQL8中引入的一个强大功能,它允许用户将JSON数据转换为关系表格式,从而可以更方便地在SQL查询中处理J... 目录基本语法示例示例查询解释应用场景不适用场景1. ‌jsON 数据结构过于复杂或动态变化‌2. ‌性能要

Python实现终端清屏的几种方式详解

《Python实现终端清屏的几种方式详解》在使用Python进行终端交互式编程时,我们经常需要清空当前终端屏幕的内容,本文为大家整理了几种常见的实现方法,有需要的小伙伴可以参考下... 目录方法一:使用 `os` 模块调用系统命令方法二:使用 `subprocess` 模块执行命令方法三:打印多个换行符模拟

SpringBoot+EasyPOI轻松实现Excel和Word导出PDF

《SpringBoot+EasyPOI轻松实现Excel和Word导出PDF》在企业级开发中,将Excel和Word文档导出为PDF是常见需求,本文将结合​​EasyPOI和​​Aspose系列工具实... 目录一、环境准备与依赖配置1.1 方案选型1.2 依赖配置(商业库方案)二、Excel 导出 PDF

SpringBoot改造MCP服务器的详细说明(StreamableHTTP 类型)

《SpringBoot改造MCP服务器的详细说明(StreamableHTTP类型)》本文介绍了SpringBoot如何实现MCPStreamableHTTP服务器,并且使用CherryStudio... 目录SpringBoot改造MCP服务器(StreamableHTTP)1 项目说明2 使用说明2.1