双亲委派机制及其部分源码分析

2023-10-30

双亲委派机制

双亲委派机制: 我理解的 双亲委派机制 简单来讲就是,类加载器加载类的时候是 自顶向下 的过程来加载。详情如下:

在某个加载器进行类加载是,会逐级向上找到他最终的父类,BootstrapClassLoader 先进行加载,逐级向下进行加载,如果某个父类加载过了则不会重新在加载,如果所有的父类都没有加载过,最后再由自己来进行加载。

类加载器的子父级关系如下(由子到父):
用户自定义类加载器 ->> appClassLoader ->> extClassLoader ->> BootstrapClassLoader

BootstrapClassLoader:根类加载器,负责加载java的核心类,是C++编写的;
ExtensionClassLoader:扩展类加载器,扩展类加载器的加载路径是JDK目录下jre/lib/ext;
AppClassLoader:应用类加载器,它负责在JVM启动时加载来自java命令的-classpath选项、java.class.path系统属性或CLASSPATH环境变量所指定的jar包和类路径。程序可以通过getSystemClassLoader()来获取系统类加载器;

使用双亲委派机制的原因:一方面防止重复加载。一方面保证系统重要类被覆盖。如果我们定义了一个的类叫java.lang.String。那么他和java自带的String类已经重复了,如果加载了我们定义的String类,那么java自己的String类就会失效。在有了双亲委派机制之后,我们自己定义的类是由appClassLoader加载的,而java.lang.String是由BootStarpClassLoader已经加载过的

部分源码如下(我加了中文版注释)

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            //第一次加载时检查该类是否已经被加载
            Class<?> c = findLoadedClass(name);
            //c==null表示该类没有被加载
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                	//如果有父类,则优先用父类进行加载。否则说明已经到了最顶层的bootstrapClassLoader,到此则开始加载
                    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) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    //父级(们)都没有加载成功,尝试自己进行加载
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    //记录一些类加载器的数据
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

打破双亲委派机制?

1, 正如上述代码描述的,如果我们重写了loadClass方法;(其实“java.” 下的任何包不会受到影响,因为已被设置为必须由BootStarpClassLoader加载,所以就算自定义类加载器加载也会失败)
2,使用线程上下文类加载器(未仔细了解,自行搜索或详见:https://blog.csdn.net/yangcheng33/article/details/52631940);

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

双亲委派机制及其部分源码分析 的相关文章

  • 强制jvm返回本机内存[重复]

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

    我想知道是否可以获取给定类的正在运行的实例的句柄 触发此问题的特定问题是应用程序由于存在大量正在运行的线程而无法正常退出 是的 我知道您可以对 thead 进行守护进程 然后它们就不会阻止应用程序退出 但这确实让我想知道这是否可能 我能做的
  • Scala REPL 中的递归重载语义 - JVM 语言

    使用 Scala 的命令行 REPL def foo x Int Unit def foo x String Unit println foo 2 gives error type mismatch found Int 2 required
  • Bipush 在 JVM 中如何工作?

    我知道 iload 接受整数 1 到 5 但是如何使用 bipush 指令扩展到更高的数字 特定整数如何与字节码一起存储 有几种不同的指令可用于推送整数常量 最小的是iconst 指令 这些只是一个字节 因为该值是在操作码本身中编码的 ic
  • 使用 javac 和 javax.tools.JavaCompiler 有什么区别?

    Maven 编译器插件文档states http maven apache org plugins maven compiler plugin 编译器插件用于编译项目的源代码 从 3 0 开始 默认编译器是 javax tools Java
  • OQL 包中的所有实例

    是否有可能在OQL检索属于一个包的所有对象 或者我可以查询wildcards 正如 haridsv 建议我尝试过的 SELECT from com example and SELECT a from com example but in V
  • 抛出 Java 异常时是否会生成堆栈跟踪?

    这是假设我们不调用 printstacktrace 方法 只是抛出和捕获 我们正在考虑这样做是为了解决一些性能瓶颈 不 堆栈跟踪是在构造异常对象时生成的 而不是在抛出异常对象时生成的 Throwable 构造函数调用 fillInStack
  • 尝试使用 Ruby Java Bridge (RJB) gem 时出现错误“无法创建 Java VM”

    我正在尝试实现 Ruby Java Bridge RJB gem 来与 JVM 通信 以便我可以运行 Open NLP gem 我在 Windows 8 上安装并运行了 Java 所有迹象 至少我所知道的 都表明 Java 已安装并可运行
  • 如果使用的 JVM 是 x86 或 x64,则以不同的方式解决 Maven 依赖关系?

    我设置了一个 Maven 存储库来托管一些 dll 但我需要我的 Maven 项目根据使用的 JVM 是 x86 还是 x64 下载不同的 dll 例如 在运行 x86 版本 JVM 的计算机上 我需要从存储库下载 ABC dll 作为依赖
  • 无法为对象堆保留足够的空间

    每次尝试运行该程序时 我都会重复出现以下异常 VM初始化期间发生错误 无法为对象堆保留足够的空间 无法创建Java虚拟机 我尝试增加虚拟内存 页面大小 和 RAM 大小 但无济于事 我怎样才能消除这个错误 运行 JVM XX MaxHeap
  • 调整 Java 类以提高 CPU 缓存友好性

    在设计java类时 对于实现CPU缓存友好性有哪些建议 到目前为止我学到的是应该尽可能多地使用 POD 即 int 而不是整数 这样 在分配包含对象时 数据将被连续分配 例如 class Local private int data0 pr
  • 是否有一种轻量级方法可以在 Java 9+ 中添加安全点

    Java 9 中是否有更便宜的方法调用可以保持其安全点 JVM 在运行时删除安全点以提高效率 但这可能会使分析和监视代码变得更加困难 为此 我们特意添加了一些简单的调用精心挑选确保存在安全点的地方 public static void sa
  • 为什么java(>=7版本)不支持运行没有main方法的程序? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 class WithoutMain static System out println Without main class Sy
  • Java:VM 如何在 32 位处理器上处理 64 位“long”

    JVM 如何在 32 位处理器上处理 64 位的原始 long 在多核 32 位机器上可以并行利用多个核心吗 64 位操作在 32 位机器上慢了多少 它可能使用多个核心来运行不同的线程 但不会并行使用它们进行 64 位计算 64 位长基本上
  • 为什么Java编译器复制finally会阻塞?

    当使用简单的代码编译以下代码时try finally块中 Java 编译器产生以下输出 在 ASM 字节码查看器中查看 Code try System out println Attempting to divide by zero Sys
  • Java:如何像 C++ 一样存储和检索内存地址

    我有 C 背景 在 C 中 我可以存储我刚刚在全局数组中新建的内存地址 并在以后重新使用它 例如 假设我有两个类 X Y 并且我创建了两个对象 x y 全局数组 StoreAddresses 2 定义为 uint32 t StoreAddr
  • Clojure 为什么命名为 Clojure

    为什么该语言的名称是 Clojure 我用谷歌搜索了一下 在 clojure 中询问 到目前为止 还没有运气 Rich Hickey 他是 Clojure 的设计者 对此的评论是 wiki 上的第一个参考链接 您是否根据以 closure
  • 在 Java 中,是否可以增加 JVM 的可用内存和/或终止其他 Java 程序?

    我对高级 Java 缺乏经验 所以请耐心等待 我对 Java 实现可称为 自主 功能的能力感到好奇 假设我们有两个 Java 程序正在运行 一个程序确定另一个程序正在占用内存 从而终止该程序和 或向 JVM 分配更多内存 我知道在 Java
  • Java:输入/使用“try-catch”块的开销?

    这个问题说明了一切 尽管命中率不是很高 我测得速度慢了 1 5 倍到 2 倍 但使用 try catch 的字节码和不使用 try catch 的字节码之间没有区别 那么是什么让它通常变慢呢 PL 请注意 问题不是抛出异常的开销 而是进入
  • 将 JVM 参数放入要在运行时获取的文件中

    我正在构建当前应用程序的 jar 它需要设置几个 JVM 参数 有没有办法在文件中而不是在命令行上设置这些 JVM 参数 我已经做了一些搜索 看起来我可以使用 java properties 文件做一些事情 可能通过设置 java args

随机推荐