Java双亲委派和类加载器

这篇具有很好参考价值的文章主要介绍了Java双亲委派和类加载器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java类生命周期

Java类加载分为以下几个步骤:
Java双亲委派和类加载器
只有加载步骤中的读取二进制流与初始化部分,能够被上层开发者,也就是大部分的Java程序员控制,而剩下的所有步骤,都是由JVM掌控,其中细节由JVM的开发人员处理,对上层开发者来说是个黑盒。

面向对象设计原则SOLID的五个原则

面向对象SOLID: 单一功能、开闭、里氏替换、接口隔离、依赖反转。

1. 单一功能原则(Single Responsibility Principle - SRP)

一个类应该只有一个单一的功能或责任。换句话说,一个类应该只有一个引起它变化的原因。这样设计可以使类更加可维护、可扩展,并降低代码耦合度。

2. 开闭原则(Open/Closed Principle - OCP)

软件实体(类、模块、函数等)应该对扩展开放、对修改关闭。这意味着在不修改原有代码的情况下,通过扩展它们来引入新的功能或行为。这样设计可以保持代码的稳定性和可维护性。

3. 里氏替换原则(Liskov Substitution Principle - LSP)

子类应该能够替换掉父类并且不影响程序的正确性。也就是说,子类应该是对父类的扩展而不是替换。遵循LSP可以保证类的继承体系的稳定性和一致性。

4. 接口隔离原则(Interface Segregation Principle - ISP)

客户端不应该被强迫依赖于它们不使用的接口。这意味着一个类不应该实现它不需要的接口。通过拆分庞大臃肿的接口为更小粒度的接口,可以提高代码的灵活性和可复用性。

5. 依赖反转原则(Dependency Inversion Principle - DIP)

高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。这样设计可以减少类之间的直接依赖,提高代码的松耦合性,从而更容易修改和维护。

主要内容

Java双亲委派和类加载器

类加载器的分类

类加载器的分类属于JVM规范,属于一种抽象的概念。各个不同的JVM实现方式不一定是一样的。

JVM规范中类加载器分为两大类,分为启动类加载器非启动类加载器

本文主要关注HotSpot虚拟机。

【补充】HotSpot虚拟机通常指的是JVM的HotSpot实现。它是Java虚拟机规范一种实现,它使用了即时编译(Just-In-Time Compilation,JIT)的技术来提高Java程序的执行性能。即时编译是一种将Java字节码直接编译成本地机器代码的技术,这样可以避免在每次执行时都解释字节码,提高程序的执行效率。

HotSpot的虚拟机的名称来源于设计目标和实现中的一个特性,即“热点代码”。热点代码通常指的是在应用程序中频繁执行的代码段。HotSpot 虚拟机通过动态编译和即时编译技术,专门优化和加速这些热点代码的执行,以提高整个应用程序的性能。

Java双亲委派和类加载器

Bootstrap ClassLoader

Bootstrap ClassLoader是嵌套在JVM内部的,它主要用于加载java的核心类库。比如<JAVA_HOME>/lib下的jar包。或者是由启动参数来指定路径下的核心类库。

此外,为了安全性,Bootstrap ClassLoader只加载了包名在白名单中的文件。

非Bootstrap ClassLoader

1. Extension ClassLoader

是由内部类ext classloader来实现的。主要加载<JAVA_HOME>/lib/ext目录下或者是由系统变量指定的路径中的类库。

Extentsion ClassLoader希望加载的是Java API的拓展,是对Java类库的一些补充能力。

2. Application ClassLoader

是由内部类app classloader来实现的。主要加载classpath/java.class.path目录下或者是系统属性指定的路径中的类库。

Application ClassLoader希望加载的是上层程序员编写的一些代码以及一些第三方的类库。可以说程序员平时编写的代码都是由Application ClassLoader来加载的。

3. User ClassLoader

可以让用户获取任何地方的字节码,并对它们进行加载。这就印证了在Java类加载机制中,允许用户从各个渠道获取class文件的二进制流来进行加载的结论。

用户自定义的类加载器只需要继承java.lang.ClassLoader, 然后单独实现获取二进制流的逻辑。而后续的步骤必须让java.lang.ClassLoader中内置的逻辑来处理。用户无权进行重写和干涉。

类加载的命名空间

问题提出

1.不同的类加载器,除了读取二进制流的动作和范围不一样,后续的加载逻辑是否也不一样?
2. 遇到限定名一样的类,这么多类加载器会不会产生混乱?

JVM规范:每个类加载器都有属于自己的命名空间

双亲委派机制

Java双亲委派和类加载器
在被动的情况下,当一个类加载器收到加载请求,他不会首先自己去加载,而是传递给自己的父亲加载器。

这样所有的类都会首先传递到最上层的Bootstrap ClassLoader,只有父亲加载器无法完成加载,那么儿子加载器才会自己去尝试加载

无法加载:根据类的限定名,类的加载器没有在自己负责的加载路径中找到该类。

【补充】在Java中,类加载器采用一种层次结构,形成了一个父子关系的链。当一个类加载器收到加载请求时,它首先会检查自己是否已经加载了这个类。如果已经加载了,那么加载过程结束。如果没有加载,类加载器会将加载请求传递给它的父类加载器。这个过程就是类加载的被动性。

被动的情况指的是在使用某个类的时候才会触发类加载过程,而不是在类被加载到内存中的时候。例如,当你在程序中使用了某个类的静态成员(静态字段、静态方法)或者创建了这个类的实例时,类加载器会被触发尝试加载这个类。在这个加载过程中,类加载器会按照一定的规则(通常是双亲委派模型)向上层加载器寻求帮助,直至根加载器。如果所有的父加载器都无法完成加载请求,那么最终由当前类加载器自己尝试加载。

这种被动加载的机制有助于保证类的唯一性和一致性,避免了重复加载,同时也利于安全性和隔离性的实现。

问题解答

  1. 不同的类加载器,除了读取二进制流的动作和范围不一样,后续的加载逻辑是否也不一样?
    我们认为除了Bootstrap ClassLoader,所有的非Bootstrap ClassLoader都继承了
    java.lang.ClassLoader,都由这个类的defineClass进行后续处理。

  2. 遇到限定名一样的类,这么多类加载器会不会产生混乱?
    越核心的类库被越上层的类加载器加载,而某限定名的类一旦被加载过了,被动情况下,就
    不会再加载相同限定名的类。这样,就能够有效避免混乱。

破坏双亲委派

但是双亲委派模型并不是一个具有强约束力的模型,因为他存在设计权限。在大部分被动情况下,他是生效并且好用的。但在一些情况可以被主动破坏。

破坏双亲委派-第一次

手动load代码破坏第一次破坏双亲委派。
Java双亲委派和类加载器

破坏双亲委派-第二次

上层的BootstrapClassLoader对下层的Application ClassLoader进行了委派加载。
Java双亲委派和类加载器

思考题

能不能自己写一个限定名为java.lang.String的类,并在程序中调用它?

如果在项目中单纯定义一个java.lang.String类,那么根据双亲委派原则会加载源码中的String,自定义类无法加载报错。如果使用自定义加载器去加载自定义的String类也不行,JDK源码好像限制了"java"开头的类,也就是保护核心源码的安全机制,防止乱改核心源码

参考资料:【JVM】Java双亲委派、类加载器这块算是玩明白了文章来源地址https://www.toymoban.com/news/detail-425331.html

到了这里,关于Java双亲委派和类加载器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入理解Java类加载机制中的双亲委派模型--根据源码探讨

    前言: 今天和大家探讨一道Java中经典的面试题,这道面试题经常出现在各个公司的面试中,本篇文章主要讲解 ava类加载机制中的双亲委派模型 的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出,对大佬有帮助

    2024年02月14日
    浏览(36)
  • 类加载 - 双亲委派机制详解

    启动类加载器(Bootstrap Class Loader):它是Java虚拟机的一部分,负责加载Java核心类库,如java.lang包中的类。它是最顶层的类加载器,由C++实现,不是Java类。 扩展类加载器(Extension Class Loader):它负责加载Java的扩展类库,位于JRE的lib/ext目录下。它是由Java编写的类加载器,是

    2024年02月12日
    浏览(31)
  • JVM类加载和双亲委派机制

    当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把类加载到JVM,本文主要说明类加载机制和其具体实现双亲委派模式。 类加载过程 : 类加载的过程是将类的字节码加载到内存中的过程,主要包括:加载--链接--初始化,其中链接还包括验证、准备、

    2024年02月09日
    浏览(32)
  • JVM:双亲委派机制&类加载器

    Java运行时环境有一个 java.lang 包,里面有一个 ClassLoader 类 我们自定义一个 String 类在 java.lang 包下,下面的main方法报错。原因是: 根据双亲委派机制,会向上找先是找到了 应用程序加载器(appClassLoader) ,然后向上找 扩展类加载器(ExtClassLoader) ,最后找 根类加载器(Boot Strap

    2024年02月01日
    浏览(27)
  • JVM类加载&双亲委派-JVM(二)

    上篇文章说了java类的加载,验证、准备、解析、初始化。类的初始化必须是类加载完才执行,所以类的构造方法初始化是在静态方法之后执行。 JVM类加载机制-JVM(一) 一、类加载和双亲委派机制 前面类加载主要通过类加载器实现,类加载器有这几种: 引导类加载器:负责

    2024年02月11日
    浏览(30)
  • JVM类加载基本流程及双亲委派模型

    一个运行起来的Java进程就是一个JVM虚拟机,这就需要从操作系统中申请一片内存区域。JVM申请到内存之后,会把这个内存划分为几个区域,每个区域都有各自的作用。 一般会把内存划分为 四个区域 : 方法区 (也称 \\\"元数据区\\\"), 堆区 , 栈区 , 程序计数器 。 (1)方法区:

    2024年04月23日
    浏览(32)
  • 从类加载到双亲委派:深入解析类加载机制与 ClassLoader

    目录 在 Java 编程中,类加载是一个关键的技术点,它负责将类引入 Java 虚拟机(JVM)使得程序能够正确地加载、链接、初始化类;类加载的过程是 Java 程序执行的基础,它涉及从磁盘或网络上加载类的字节码,解析类的符号引用,最终将类加载到内存中供程序使用 类加载的

    2024年02月11日
    浏览(30)
  • JVM的类加载的过程以及双亲委派模型

    目录 1、加载 (加载字节码文件,生成.class对象) 2、验证(验证Class文件是否符合规范)  3、准备 (为静态变量分配内存并设置变量初始值) 4、解析(初始化常量池中的一些常量)  5、初始化(初始化对象,并为静态变量赋值)  总结: 双亲委派模型:   JVM的类加载器

    2023年04月20日
    浏览(34)
  • JVM(类的加载与ClassLoader、双亲委派机制)

    类在内存中完整的生命周期: 加载--使用--卸载 。其中加载过程又分为: 装载、链接、初始化 三个阶段。 当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载、链接、初始化三个步骤来对该类进行初始化。如果没有意外,JVM将会连续完成这三个步骤,

    2024年02月03日
    浏览(33)
  • 深度解析JVM类加载器与双亲委派模型

    Java虚拟机(JVM)是Java程序运行的核心,其中类加载器和双亲委派模型是JVM的重要组成部分。本文将深入讨论这两个概念,并解释它们在实际开发中的应用。 1. 什么是类加载器? 类加载器是JVM的一部分,负责加载Java类的字节码文件。Java应用程序中的每个类都必须由类加载器

    2024年01月17日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包