ClassLoader如何加载class

简介: ClassLoader如何加载class


ClassLoader是经常出现又让很多人望而却步的词,所以我将试图用最浅显易懂的方式来说一下ClassLoader,希望对不了解该机制的朋友们能起到一点点的作用。

要深入了解ClassLoader,首先就要知道ClassLoader是用来干什么的,顾名思义,它就是用来加载Class文件到JVM(Java Virtual Machine(Java虚拟机)的缩写)。以供程序使用的。我们知道,Java程序可以动态加载类定义,而这个动态加载的机制就是通过ClassLoader来实现的,所以可想而知ClassLoader的重要性如何。

看到这里,可能有的朋友会想到一个问题,那就是既然ClassLoader是用来加载类到JVM中的,那么ClassLoader又是如何被加载的呢,难道他不是Java的类吗?

没有错,在这里确实有一个ClassLoader不是用Java语言所编写的,而是JVM实现的一部分,这个ClassLoader就是bootstrap classloader(启动类加载器),这个ClassLoader在JVM运行的时候加载Java核心的API以满足Java程序最基本的需求,其中就包括用户自定义的ClassLoader,这里所谓的用户自定义是指通过Java程序实现的ClassLoader,一个是ExtClassLoader,这个ClassLoader是用来加载Java的扩展API的,也就是/lib/ext中的类。另一个是AppClassLoader,这个ClassLoader是用来加载用户机器上CLASSPATH设置目录中的class的,通常在没有指定ClassLoader的情况下,我们程序员自定义的类就由该ClassLoader进行加载。

当运行一个程序的时间,JVM启动,运行bootstrap classloader,该ClassLoader加载Java核心API(ExtClassLoader和APPClassLoader也在此时被加载),然后调用ExtClassLoader加载扩展API,最后APPClassLoader加载CLASSPATH目录下定义的class,这就是一个程序最基本的加载流程。

上面大概解释了一下ClassLoader的作用以及一个最基本的加载流程,下面来解释一下ClassLoader加载的方式,说到ClassLoader的加载方式,不得不解释一下ClassLoader在这里使用了双亲委托模式进行类加载。

每一个自定义ClassLoader都必须继承ClassLoader这个抽象类,而每个ClassLoader都会有一个parent ClassLoader,我们可以看一下ClassLoader这个抽象类中有一个getParent()方法,这个方法用来返回当前ClassLoader的parent,注意,这个parent不是指定的被继承的类,而是在实例化该ClassLoader时指定的一个ClassLoader,如果这个parent为null,那么就默认该ClassLoader的parent是bootstrap classloader,这个parent有什么用呢?

我们可以考虑这样一种情况,假设我们自定义了一个ClientDefClassLoader,我们使用这个自定义的ClassLoader加载java.lang.String,那么这里String是否会被这个ClassLoader加载呢?事实上,java.lang.String这个类并不是被这个ClientDefClassLoader加载,而是由bootstrap classloader进行加载,为什么会这样?实际上这就是双亲委托模式的原因,因为在任何自定义ClassLoader加载一个类之前,它都会先委托它的父亲ClassLoader进行加载,只有当父亲ClassLoader无法加载成功后,才会由自己加载,在上面这个例子里,因为java.lang.String是属于Java核心API的一个类,所以当使用ClientDefClassLoader加载它的时候,该ClassLoader会先委托他的父亲ClassLoader进行加载,上面说过,当ClassLoader的parent为null时,ClassLoader的parent就是bootstrap classloader,所以在ClassLoader的最顶层就是bootstrap classloader,因此最终委托到bootstrap classloader的时候,bootstrap classloader就会返回String的Class。

下面我们看一下ClassLoader中的一段源码:

public class Snippet{

protected synchronized Class loadClass(String name,boolean resolve) throws
    ClassNotFoundException{
    //首先检查该name指定的class是否被加载
    Class c = findLoadedClass(name);
    if(c==null){
        try{
            if(parent!=null){
            //如果parent不为null,则调用parent的loadClass进行加载
            c=parent.loadClass(name,false);
            }else{
            //如果parent为null,则调用BootstrapClassLoader进行加载
            c=findBootstrapClass0(name);
            }
   }catch(ClassNotFoundException e){
        //如果仍然无法加载成功,则调用自身的findClass进行加载
        c=findClass(name);
    }

}
if(resolve){resolveClass(c);}
return c;
}
}
从上面的一段代码,我们可以看出一个类加载的大概过程,与我们刚开始所举的例子是一样的,而我们要实现一个自定义类的时间,只需要实现findClass方法即可。

相关文章
|
Oracle 安全 关系型数据库
搭建 OpenLDAP 自助修改密码系统
让修改open ldap密码变得简单
2018 0
搭建 OpenLDAP 自助修改密码系统
|
6月前
|
机器学习/深度学习 人工智能 算法
ICLR 2026|面向问题 + 锚点验证,解锁 LLM 代码优化新范式
软件工程中代码效率优化至关重要。本文提出一种全新大模型代码优化方案,采用面向问题的优化视角与锚点验证框架,突破局部改进局限与优化税瓶颈,显著提升优化效果、执行效率与代码可靠性,为大模型自动化高性能代码生成开辟实用化新路径。
474 1
|
3月前
|
人工智能 缓存 API
阿里云千问大模型Qwen3.7-Max功能、免费试用、订阅计费、配置接入详解
阿里云千问Qwen3.7-Max是面向智能体时代打造的旗舰大语言模型,专为复杂推理、长文本处理、代码工程与长周期自主任务优化,在编程、办公自动化、科研推理等领域具备顶尖能力。以下从核心功能、免费试用、订阅计费、配置接入四大维度,全面解析该模型的使用与接入细节。
571 4
|
存储 机器学习/深度学习 人工智能
MXFP4量化:如何在80GB GPU上运行1200亿参数的GPT-OSS模型
GPT-OSS通过MXFP4量化技术实现1200亿参数模型在单个80GB GPU上的高效运行,将权重压缩至每参数4.25位,大幅降低内存需求,同时保持高精度和竞争力的基准性能,为大规模模型部署提供了新思路。
1111 13
MXFP4量化:如何在80GB GPU上运行1200亿参数的GPT-OSS模型
|
5月前
|
Web App开发 Rust 前端开发
基于Rust开发的m3u8下载器:支持断点续传、边下边播
M3U8 Quicker是一款轻量(仅2MB)跨平台M3U8下载播放器,基于Tauri+Rust+React开发。支持断点续传、AES解密、边下边播、自动转MP4及Chrome一键抓取地址,让课程保存与媒体管理更高效稳定。
990 4
|
5月前
|
存储 监控 测试技术
ES索引的基础和进阶内容
本文详解Elasticsearch索引创建与优化:涵盖默认、自定义配置及模板三种创建方式;深入分片/副本数选型策略(建议分片10–50GB);详述reindex全流程(含切片加速、限速、监控与安全删除);解析object/nested/wildcard等核心字段类型差异;并介绍动态/显式映射、索引模板与别名等进阶实践。(239字)
382 0
|
人工智能 自然语言处理 搜索推荐
创新场景丨听力熊:让 1 亿 10 后拥有“随身智能体”
大模型在青少年场景的应用价值已经远超其它传统教育硬件,听力熊由此也开始向 AI 随身智能体转型。
|
10月前
|
JSON API 开发者
淘宝平台获取商品视频 API 接口技术指南
本文介绍如何通过淘宝开放平台API获取商品视频信息,涵盖开发者账号注册、应用创建、API调用流程及Python代码示例,助您快速实现商品视频数据的提取与集成,适用于数据分析与第三方应用开发。
1807 0
|
前端开发 Android开发 UED
讲讲Android为自定义view提供的SurfaceView
本文详细介绍了Android中自定义View时使用SurfaceView的必要性和实现方式。首先分析了在复杂绘制逻辑和高频界面更新场景下,传统View可能引发卡顿的问题,进而引出SurfaceView作为解决方案。文章通过Android官方Demo展示了SurfaceView的基本用法,包括实现`SurfaceHolder.Callback2`接口、与Activity生命周期绑定、子线程中使用`lockCanvas()`和`unlockCanvasAndPost()`方法完成绘图操作。
398 3
|
存储 固态存储 算法
固态硬盘损坏后还能做数据恢复吗?完整指南
固态硬盘(SSD)因速度快、抗震动、低噪音被广泛使用,但一旦损坏,用户常因慌乱导致二次损失。本文解析SSD损坏后的数据恢复可行性,介绍逻辑损坏、固件异常、物理损坏三种常见情况,并提供对应的恢复方法与预防措施,帮助用户科学应对数据丢失风险,提升恢复成功率。