(JVM)Java中啃老的类加载器与双亲委派机制

Java 编译之后生成的字节码文件,进入执行阶段,首先要进入 Java 虚拟机被加载。
那么加载的过程是什么样?不同层级的类被加载进 元空间(Metaspace) 时,它们分别要被哪几个加载器加载呢?


一、JVM 的四种类加载器

JVM 并不是直接把类“吃掉”,而是要分层次、分角色地去加载不同来源的类。主要有以下几种加载器:

  1. 启动类加载器(Bootstrap ClassLoader)

    • 作用:加载核心类库(比如 java.lang.*java.util.* 等)。

    • 举例:加载 StringObjectInteger

    • 特点:由 C++ 实现,不是普通 Java 对象,看不见也碰不到。

  2. 扩展/平台类加载器(Extension / Platform ClassLoader)

    • 作用:加载 JDK 扩展目录中的类库(早期是 jre/lib/ext,Java 9 之后叫 Platform ClassLoader,加载一些平台模块)。

    • 举例:javax.crypto.*javax.sql.*

  3. 应用程序类加载器(Application / System ClassLoader)

    • 作用:加载应用的类路径(Classpath)下的类,也就是我们写的普通 Java 代码,以及依赖的第三方 jar 包。

    • 举例:你写的 com.xxx.Main、项目中引入的 Spring 框架。

  4. 自定义类加载器(Custom ClassLoader)

    • 作用:用户自己写的,通常用来实现特殊需求(比如从网络、数据库、加密文件里加载 class)。

    • 举例:Tomcat、Spring Boot 就会自定义类加载器来隔离不同模块的 class。


二、类加载器是干什么的?

一句话:类加载器的职责就是把 .class 文件读进来,转化成 JVM 可以理解的 Class 对象,并放到元空间(Metaspace)里。

换句话说,它就像是“搬运工 + 翻译机”:

  • 搬运工:找到字节码文件(无论是本地磁盘、网络、jar 包)。

  • 翻译机:把字节码转成 JVM 内部的运行时数据结构,存放在元空间,等待方法区等运行时结构使用。


三、双亲委派机制

既然有这么多加载器,那问题来了:加载的时候到底谁来干活?
这里就有一个“啃老”的机制——双亲委派机制(Parent Delegation Model)

流程是这样的:

  1. 当某个类加载器接到加载请求时,它自己先不急着动手。

  2. 它会先把请求“往上交”,让自己的父类加载器去尝试加载。

  3. 这样一层层往上,直到 启动类加载器(Bootstrap)

  4. 如果父类加载器都说:“我不认识这个类”,请求才会一层层退回来,最后由自己来加载。

打个比方:
就像写作业不会的题,先问爸爸,爸爸不会问爷爷,爷爷不会问太爷爷。
如果全家都不会,最后只能靠自己硬着头皮去写。


四、双亲委派的意义

为什么要搞这么一套“啃老”的机制呢?
主要有三个原因:

  1. 避免重复加载

    • 父类加载器如果已经加载过某个类,子类加载器就不用重复加载了。

  2. 保证核心类的安全性

    • 假如没有双亲委派,你可以写一个自定义的 java.lang.String,试图“顶替”JDK 的 String

    • 有了双亲委派,JVM 会优先用 Bootstrap 已经加载的核心 String,屏蔽掉用户代码的冒充。

  3. 实现模块化与隔离

    • 应用类和第三方库只管加载自己的,不会干扰到 JVM 核心类。

    • 各个 Web 容器、自定义 ClassLoader 也能通过这套机制实现类隔离。


五、加载类的最终目的

类加载的本质目的就是:
把字节码文件(.class)转成 JVM 内部的 Class 对象,并放入元空间(Metaspace)。

元空间中保存了类的方法、字段、常量池、运行时结构等信息,供 JVM 在运行期使用。
真正的对象实例化(分配在堆上)要等到 new 的时候才发生。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值