简述ClassLoader双亲委派模式

简介: 简述ClassLoader双亲委派模式

前言

我们的面试中经常会遇到关于ClassLoader的问题,但是我们的日常开发中又没有直接编写过ClassLoader相关的代码。对于小白新手来说,可能都不知道ClassLoader是用来干嘛的,它是如何在无形当中影响我们编写的代码的?

ClassLoader的作用

见名知意,ClassLoader就是类加载器,它的作用就是将我们编写的java代码加载到JVM虚拟机中。在JVM启动的时候是不会一次性把所有的java类加载进去的,而是在需要的时候才加载指定的类文件,要不然类特别多的话,大部分类一时用不上,那就浪费内存资源了。既然ClassLoader是用来加载类文件的,那么我们平时写的java代码是如何加载的呢?

ClassLoader的种类

在JDK中,默认是有三种ClassLoader的:

  • Bootstrap ClassLoader
    主要加载核心类库,加载${JRE_HOME}/lib下的rt.jar、resources.jar等;
  • Extension ClassLoader
    加载扩展类库,加载${JRE_HOME}/lib/ext文件夹下的jar包和class文件;另外还会加载-D java.ext.dirs指定的目录下的jar包和class文件;
  • AppClassLoader
    加载当前应用classpath下的所有class文件;

如何实现双亲委派模式

Launcher类中,我们可以看到Launcher创建的时候,同时创建了ExrClassLoaderAppClassLoader对象。

sun.misc.Launcher:

public Launcher() {
        Launcher.ExtClassLoader var1;
        try {
            var1 = Launcher.ExtClassLoader.getExtClassLoader();
        } catch (IOException var10) {
            throw new InternalError("Could not create extension class loader", var10);
        }
        try {
            this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
        } catch (IOException var9) {
            throw new InternalError("Could not create application class loader", var9);
        }
        Thread.currentThread().setContextClassLoader(this.loader);
    }
复制代码

1.创建ExtClassLoader对象;

2.创建AppClassLoader对象,并把ExtClassLoader对象作为AppClassLoader的父级ClassLoader;

3.把AppClassLoader对象绑定到线程上下文中;

为什么没有提到BoostrapClassLoader?因为BoostrapClassLoader在java层面是拿不到的,ExtClassLoader的父级ClassLoader就是BoostrapClassLoader,java层面取出来就是null;

为了了解清楚类的加载方式,我们首先需要从AppClassLoader中的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 {
                    // 如果父级ClassLoader不为空,那么就先尝试让父级ClassLoader加载
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        // 如果父级ClassLoader为空,有可能父级ClassLoader是BootstrapClassLoader,那么先尝试在BootstrapClassLoader加载
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
                // 如果一直向上都没有加载目标class,那么最终回到当前ClassLoader加载
                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.先在当前ClassLoader检查是否已经加载了目标类;
2.如果当前ClassLoader没有加载目标类,那么先向尝试让父级ClassLoader加载目标类,直至BootstrapClassLoader;
3.如果最终所有的父级ClassLoader都没有加载目标类,那么当前ClassLoader尝试自己加载目标类;
4.所有父级ClassLoader重复操作1~3步骤;
5.只要其中任意一个ClassLoader成功加载目标类,那么就直接返回;
复制代码

小测试

为了验证小伙伴们是否已经明白了双亲委派模式,我们出一个小小的测试题留给大家:

我们通过自己创建一个java.lang.String的类(类名和包名和JDK中的String.class一致),这个自定义的String类能不能通过AppClassLoader成功地加载到JVM中?

知道答案的小伙伴可以在评论区留言哦!!!


相关文章
|
机器学习/深度学习 算法 数据挖掘
Python | 机器学习之聚类算法
Python | 机器学习之聚类算法
862 0
|
SQL Java 数据库连接
“MyBatis中的动态SQL、模糊查询与结果映射“
“MyBatis中的动态SQL、模糊查询与结果映射“
466 0
|
存储 安全 关系型数据库
MySQL的安全性维护
MySQL安全管理
262 0
|
21小时前
|
存储 JavaScript 前端开发
JavaScript基础
本节讲解JavaScript基础核心知识:涵盖值类型与引用类型区别、typeof检测类型及局限性、===与==差异及应用场景、内置函数与对象、原型链五规则、属性查找机制、instanceof原理,以及this指向和箭头函数中this的绑定时机。重点突出类型判断、原型继承与this机制,助力深入理解JS面向对象机制。(238字)
|
1天前
|
安全 数据可视化 网络安全
安全无小事|阿里云先知众测,为企业筑牢防线
专为企业打造的漏洞信息收集平台
1296 2
|
2天前
|
云安全 人工智能
2025,阿里云安全的“年度报告”
拥抱AI时代,阿里云安全为你护航~
1445 1
|
9天前
|
机器学习/深度学习 安全 API
MAI-UI 开源:通用 GUI 智能体基座登顶 SOTA!
MAI-UI是通义实验室推出的全尺寸GUI智能体基座模型,原生集成用户交互、MCP工具调用与端云协同能力。支持跨App操作、模糊语义理解与主动提问澄清,通过大规模在线强化学习实现复杂任务自动化,在出行、办公等高频场景中表现卓越,已登顶ScreenSpot-Pro、MobileWorld等多项SOTA评测。
1372 7
|
10天前
|
人工智能 Rust 运维
这个神器让你白嫖ClaudeOpus 4.5,Gemini 3!还能接Claude Code等任意平台
加我进AI讨论学习群,公众号右下角“联系方式”文末有老金的 开源知识库地址·全免费
1246 15
|
4天前
|
人工智能 前端开发 API
Google发布50页AI Agent白皮书,老金帮你提炼10个核心要点
老金分享Google最新AI Agent指南:让AI从“动嘴”到“动手”。Agent=大脑(模型)+手(工具)+协调系统,可自主完成任务。通过ReAct模式、多Agent协作与RAG等技术,实现真正自动化。入门推荐LangChain,文末附开源知识库链接。
476 118

热门文章

最新文章