返回顶部
首页 > 资讯 > 精选 >JVM的类加载器和双亲委派模式实例分析
  • 320
分享到

JVM的类加载器和双亲委派模式实例分析

2023-06-29 12:06:17 320人浏览 薄情痞子
摘要

这篇文章主要讲解了“JVM的类加载器和双亲委派模式实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JVM的类加载器和双亲委派模式实例分析”吧!类加载器Java虚拟机设计团队有意把类加载

这篇文章主要讲解了“JVM的类加载器和双亲委派模式实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JVM的类加载器和双亲委派模式实例分析”吧!

    类加载器

    Java虚拟机设计团队有意把类加载阶段中的“通过一个类的全限定名来获取描述该类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需的类。实现这个动作的代码被称为“类加载器”(ClassLoader)。

    对于任意一个类,都必须由加载它的类加载器和这个类本身一起共同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。这句话可以表达得更通俗一些:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个Java虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等

    名称加载的类说明
    Bootstrap ClassLoader(启动类加载器)JAVA_HOME/jre/lib无法直接访问
    Extension ClassLoader(拓展类加载器)JAVA_HOME/jre/lib/ext上级为Bootstrap,显示为null
    Application ClassLoader(应用程序类加载器)classpath上级为Extension
    自定义类加载器自定义上级为Application

    1、启动类加载器

    可通过在控制台输入指令,使得类被启动类加器加载,它是用c++写的,看不到源码;其他类加载器是用Java写的,说白了就是一些Java类,比如扩展类加载器、应用类加载器。

    //查询所有被启动类加载器加载的类URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();for (URL url : urls) {    System.out.println(url);}
    //查询到的结果file:/C:/Program%20Files/Java/jre1.8.0_131/lib/resources.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/rt.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/sunrsasign.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/jsse.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/jce.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/charsets.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/jfr.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/classes

    由上可以看出启动类加载的都是jre和jre/lib目录下的核心库,具体路径要看你的jre安装在哪里

    2、拓展类加载器

    如果classpath和JAVA_HOME/jre/lib/ext 下有同名类,加载时会使用拓展类加载器加载。当应用程序类加载器发现拓展类加载器已将该同名类加载过了,则不会再次加载

    URL[] urls = ((URLClassLoader) ClassLoader.getSystemClassLoader().getParent()).getURLs();for (URL url : urls) {    System.out.println(url);}
    file:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/access-bridge-64.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/cldrdata.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/dnsns.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/dns_sd.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/jaccess.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/jfxrt.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/localedata.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/nashorn.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/sunec.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/sunjce_provider.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/sunmscapi.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/sunpkcs11.jarfile:/C:/Program%20Files/Java/jre1.8.0_131/lib/ext/zipfs.jar

    这些类库具体是什么不重要,只需要知道不同的类库可能是被不同的类加载器加载的。

    3、应用程序类加载器

    URL[] urls = ((URLClassLoader) ClassLoader.getSystemClassLoader()).getURLs();for (URL url : urls) {    System.out.println(url);}
    file:/{项目工程目录}/bin/

    这是当前java工程的bin目录,也就是我们自己的Java代码编译成的class文件所在。

    4、双亲委派模式

    双亲委派模式,调用类加载器ClassLoader 的 loadClass 方法时,查找类的规则。

    loadClass源码

    protected Class<?> loadClass(String name, boolean resolve)    throws ClassNotFoundException{    synchronized (getClassLoadingLock(name)) {        // 首先查找该类是否已经被该类加载器加载过了        Class<?> c = findLoadedClass(name);        //如果没有被加载过        if (c == null) {            long t0 = System.nanoTime();            try {                //看是否被它的上级加载器加载过了 Extension的上级是Bootstarp,但它显示为null                if (parent != null) {                    c = parent.loadClass(name, false);                } else {                    //看是否被启动类加载器加载过                    c = findBootstrapClassOrNull(name);                }            } catch (ClassNotFoundException e) {                // ClassNotFoundException thrown if class not found                // from the non-null parent class loader                //捕获异常,但不做任何处理            }            if (c == null) {                //如果还是没有找到,先让拓展类加载器调用findClass方法去找到该类,如果还是没找到,就抛出异常                //然后让应用类加载器去找classpath下找该类                long t1 = System.nanoTime();                c = findClass(name);                // 记录时间                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);                sun.misc.PerfCounter.getFindClasses().increment();            }        }        if (resolve) {            resolveClass(c);        }        return c;    }}

    有一个描述类加载器加载类过程的术语:双亲委派模型。然而这是一个很有误导性的术语,它应该叫做单亲委派模型(Parent-Delegation Model)。但是没有办法,大家都已经这样叫了。所谓双亲委派,这个亲就是指ClassLoader里的全局变量parent,也就是父加载器。

    双亲委派的具体过程如下:

    • 当一个类加载器接收到类加载任务时,先查缓存里有没有,如果没有,将任务委托给它的父加载器去执行。

    • 父加载器也做同样的事情,一层一层往上委托,直到最顶层的启动类加载器为止。

    • 如果启动类加载器没有找到所需加载的类,便将此加载任务退回给下一级类加载器去执行,而下一级的类加载器也做同样的事情。

    • 如果最底层类加载器仍然没有找到所需要的class文件,则抛出异常。

    • 所以是一条线传上再传下,并没有什么“双亲”。

    JVM的类加载器和双亲委派模式实例分析

    为什么要双亲委派?

    :确保类的全局唯一性。

    如果你自己写的一个类与核心类库中的类重名,会发现这个类可以被正常编译,但永远无法被加载运行。因为你写的这个类不会被应用类加载器加载,而是被委托到顶层,被启动类加载器在核心类库中找到了。如果没有双亲委托机制来确保类的全局唯一性,谁都可以编写一个java.lang.Object类放在classpath下,那应用程序就乱套了。

    安全的角度讲,通过双亲委托机制,Java虚拟机总是先从最可信的Java核心API查找类型,可以防止不可信的类假扮被信任的类对系统造成危害。

    5、自定义类加载器

    如果我们自己去实现一个类加载器,基本上就是继承ClassLoader之后重写findClass方法,且在此方法的最后调包defineClass。

    5.1、使用场景
    • 想加载非 classpath 随意路径中的类文件

    • 通过接口来使用实现,希望解耦时,常用在框架设计

    • 这些类希望予以隔离,不同应用的同名类都可以加载,不冲突,常见于 Tomcat 容器

    5.2、步骤
    • 继承ClassLoader父类

    • 要遵从双亲委派机制,重写 findClass 方法

      • 不是重写loadClass方法,否则不会走双亲委派机制

    • 读取类文件的字节码

    • 调用父类的 defineClass 方法来加载类

    • 使用者调用该类加载器的 loadClass 方法

    protected Class<?> findClass(final String name) throws ClassNotFoundException {    // 1、安全检查    // 2、根据绝对路径把硬盘上class文件读入内存    byte[] raw = getBytes(name);     // 3、将二进制数据转换成class对象    return defineClass(raw);}

    感谢各位的阅读,以上就是“JVM的类加载器和双亲委派模式实例分析”的内容了,经过本文的学习后,相信大家对JVM的类加载器和双亲委派模式实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

    --结束END--

    本文标题: JVM的类加载器和双亲委派模式实例分析

    本文链接: https://lsjlt.com/news/324634.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • JVM的类加载器和双亲委派模式实例分析
      这篇文章主要讲解了“JVM的类加载器和双亲委派模式实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JVM的类加载器和双亲委派模式实例分析”吧!类加载器Java虚拟机设计团队有意把类加载...
      99+
      2023-06-29
    • JVM的类加载器和双亲委派模式你了解吗
      目录类加载器1、启动类加载器2、拓展类加载器3、应用程序类加载器4、双亲委派模式5、自定义类加载器5.1、使用场景5.2、步骤总结类加载器 Java虚拟机设计团队有意把类加载阶段中的...
      99+
      2024-04-02
    • 自定义类加载器以及打破双亲委派模型解析
      目录1 自定义类加载器2 打破双亲委派模型1 自定义类加载器自定义类加载器的代码很简单,只需要继承ClassLoader类,覆写findClass方法即可其默认实现是会抛出...
      99+
      2022-11-21
      自定义类加载器 双亲委派模型
    • Java虚拟机类加载器之双亲委派机制模型案例
      1. 双亲委派模型是什么? 当某个类加载器需要加载某个.class字节码文件时,它首先把这个任务委托给它的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类...
      99+
      2024-04-02
    • Java类加载器与双亲委派机制和线程上下文类加载器专项解读分析
      目录一、类加载器1.启动类加载器2.拓展类加载器3.应用类加载器4.类的命名空间二、双亲委派机制1.类加载机制流程2.类加载器加载顺序3.双亲委派机制流程4.源码分析5.双亲委派机制...
      99+
      2022-12-22
      Java类加载器 Java双亲委派机制 Java线程上下文类加载器
    • Java虚拟机之对象创建过程与类加载机制及双亲委派模型
      目录一、对象的创建过程: 1、对象的创建过程:2、对象的访问方式:二、类加载机制:2.1、加载阶段:2.2、验证阶段:2.3、准备阶段:2.4、解析阶段:2.5、初始化:2...
      99+
      2024-04-02
    • JVM类加载场景的实例分析
      JVM类加载场景的实例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。JVM是Java Virtual  Machine(Java虚拟机)的缩写,J...
      99+
      2023-06-16
    • jvm中类加载过程的示例分析
      这篇文章主要介绍jvm中类加载过程的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!类加载过程:1、加载阶段;2、验证阶段;3、准备阶段,主要是将类变量在方法区进行内存分配并进行初始化;4、解析阶段;5、初始化...
      99+
      2023-06-20
    • Android中的类文件和类加载器实例分析
      本篇内容介绍了“Android中的类文件和类加载器实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、Java中的类加载器首先花点时间...
      99+
      2023-06-30
    • classloader类加载器基于java类的加载方式的示例分析
      这篇文章主要介绍classloader类加载器基于java类的加载方式的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!基础概念Classloader 类加载器,用来加载 Java 类到 Java 虚拟机中。与...
      99+
      2023-05-31
      classloader java
    • java类加载器的示例分析
      这篇文章给大家分享的是有关java类加载器的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Java的优点是什么1. 简单,只需理解基本的概念,就可以编写适合于各种情况的应用程序;2. 面向对象;3. 分布...
      99+
      2023-06-14
    • javascript模块加载器的示例分析
      这篇文章将为大家详细讲解有关javascript模块加载器的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。定义var MyModules =&...
      99+
      2024-04-02
    • Android的Activity加载方式实例分析
      本文实例分析了Android的Activity加载方式。分享给大家供大家参考,具体如下: 前面分析过Android中activity的加载方式(参考前面一篇《Android编程...
      99+
      2022-06-06
      activity Android
    • Angular中模块和懒加载的示例分析
      这篇文章主要介绍Angular中模块和懒加载的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、Angular 内置模块二、Angular 自定义模块当我们项目比较小的时候可以不用自定义模块。但是当我们项目非...
      99+
      2023-06-06
    • Java中观察者模式与委托的实例对比分析
      这篇文章主要介绍“Java中观察者模式与委托的实例对比分析”,在日常操作中,相信很多人在Java中观察者模式与委托的实例对比分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中观察者模式与委托的实例对...
      99+
      2023-06-30
    • js简易模块加载器的示例分析
      这篇文章主要为大家展示了“js简易模块加载器的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js简易模块加载器的示例分析”这篇文章吧。前端模块化关注前端...
      99+
      2024-04-02
    • Awk的BEGIN和END模式实例分析
      本篇内容介绍了“Awk的BEGIN和END模式实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!awk是Unix环境下一种非常好的语言,...
      99+
      2023-06-27
    • java访问者模式的静态动态及伪动态分派实例分析
      今天小编给大家分享一下java访问者模式的静态动态及伪动态分派实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1 使用...
      99+
      2023-07-02
    • Java的单例模式与final及抽象类和接口实例分析
      这篇文章主要介绍“Java的单例模式与final及抽象类和接口实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java的单例模式与final及抽象类和接口实例分析”文章能帮助大家解决问题。1....
      99+
      2023-06-30
    • Spark SQL数据加载和保存的实例分析
      今天就跟大家聊聊有关Spark SQL数据加载和保存的实例分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、前置知识详解 Spark SQL重要...
      99+
      2024-04-02
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作