深入类加载器-类加载器作用,类缓存、类加载器的层次结构、ClassLoader类介绍、代理模式之双亲委派机制

本文详细探讨了Java类加载器的角色,包括其在加载class字节码文件到内存中的作用,类缓存的原理,以及类加载器的层次结构。重点解析了ClassLoader类的功能和相关方法,并详细阐述了代理模式下的双亲委派机制,这是保障Java核心库安全的重要策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、类加载器的作用

类加载器的作用是将class字节码文件加载到内存中,并将这些静态数据转化为方法区中的运行时数据结构,同时在堆中生成代表这个类的java.lang.Class对象,作为访问方法区中数据的入口。

2、类缓存

标准的Java SE类加载器可以按要求查找指定的类,但是一旦某个类被加载到指定的类加载器中,它将维持一段时间,不过,JVM垃圾回收机制可以回收这些Class对象,简单的说,类在被回收前,只被加载一次

3、类加载器的层次结构

*注意:

a、只有引导类加载器没有继承java.lang.ClassLoader

b、只有引导类加载器是用C++写的,其他的类加载都是用java写的

c、自定义类的加载器的父类是应用程序类加载器,应用程序类加载器的父类是拓展类类加载,拓展类类加载的父类是引导类加载器,引导类加载器没有父类

d、注意这里所说的父类并不是继承的关系,内部的采用的组合的方式实现的
————————————————————————————

1. 引导类加载器(bootstrap class loader)

作用:

1、加载Java的核心库(JAVA_HOME/jre/lib/rt.jar)或sun.boot.class.path路径下的内容

2、加载扩展类和应用程序类加载器,并指定他们的父类

3、它是由原生程序C++写的,并不继承java.lang.Classloader

通过程序获取sun.boot.class.path路径下的内容

@org.junit.Test
    public void test() {
        System.out.println(System.getProperty("sun.boot.class.path"));
    }

程序执行结果:

这里写图片描述

2、扩展类加载器(Extensions class loader)

1、用来加载java的扩展库(JAVA_HOME/jre/ext/*.jar)或java.ext.dirs路径下的内容,Java虚拟机会提供一个扩展库目录,该类加载器在这里查找并加载java类

2、由sun.misc.Launcher$ExtClassLoader实现

3、应用程序类加载器(application class loader)

1、根据Java应用的类路径来加载类,一般来说Java应用的类都是由它来加载的

2、由sun.misc.Launcher$AppClassLoader实现

4、自定义类加载器

1、开发人员可以通过继承java.lang.ClassLoader类来定义自己的类加载器已满足一些特殊的需求

4、ClassLoader类介绍

作用
  1. 加载字节码文件并生成对应的java.lang.Class对象

  2. 加载Java应用所需要的资源,如图像和配置文件

相关方法
方法解释
getParent()返回该类加载器的父类加载器
loadClass(String name)加载返回名称为name的java.lang.Class实例
findClass(String name)找到并返回名称为name的java.lang.Class实例
findLoadedClass(String name)查找并返回已经加载过的名称为name的java.lang.Class实例
defineClass(String name,byte[]b,int off,int len)方法为final不能被重写,通过byte字节数组生成并返回名称为name的java.lang.Class实例

*注意

  1. 上面方法参数中的name指定的是类的二进制名,需要注意的是内部类的表示,com.maple.example$Test表示内部类Test

5、代理机制之双亲委派机制

解释:

某个类加载执行类加载请求时,先将该请求交给父类,父类再交给父类的父类,知道最高级父类,到达最高级父类时,他会判断我能不能加载这个类,如果能,则加载成功返回,如果不能,则交给他的一级子类重复以上的操作,知道这个类最后被成功加载

作用:

保证了Java核心库的类型安全,这种机制也是java很重要的安全屏障

### Java 类加载器工作机制 Java 的类加载器ClassLoader)是 JVM 运行时环境的一部分,负责动态加载 `.class` 文件到内存中,并将其转换为 `Class` 对象。整个过程遵循一定的规则和层次结构,其中最核心的部分就是 **双亲委派模型**。 #### 双亲委派模型概念 双亲委派模型是一种加载机制,在该模型下,当一个类加载器收到加载请求时,它并不会立即尝试自己加载这个,而是先把这个请求委托给它的父类加载器处理。如果父类加载器能够成功加载,则返回对应的 `Class` 实例;否则,子类加载器再自行尝试加载[^4]。 这种设计的主要目的是为了保证 Java 核心库的安全性和一致性。例如,所有的标准 JDK 都会由启动类加载器(Bootstrap ClassLoader)加载,这确保了这些在整个应用程序生命周期内的唯一性[^5]。 --- ### 类加载器的分及其作用 在 Java 中,存在三种主要型的类加载器: 1. **启动类加载器(Bootstrap ClassLoader)** - 负责加载 Java 核心库中的(如 `java.lang.*`, `java.util.*`),通常位于 `$JAVA_HOME/lib/rt.jar` 或其他指定路径下的 JAR 文件中。 - 它是由本地代码实现的,因此无法直接获取其实例对象[^3]。 2. **扩展类加载器(Extension ClassLoader)** - 加载存放在 `$JAVA_HOME/lib/ext` 目录或者通过 `java.ext.dirs` 系统属性指定位置中的 JAR 包。 - 扩展类加载器继承自 `URLClassLoader`,可以通过编程方式访问其实例[^1]。 3. **应用程序类加载器(Application ClassLoader / System ClassLoader)** - 默认用于加载用户的应用程序,默认从 `-classpath` 参数或环境变量 `CLASSPATH` 指定的位置读取资源。 - 开发者也可以创建自己的自定义类加载器来满足特定需求[^2]。 --- ### 双亲委派模型的具体流程 以下是双亲委派模型的实际执行逻辑描述: 1. 当某个类加载器接收到加载请求时,首先判断此请求是否已经被缓存过。如果是已加载过的,则直接返回现有的 `Class` 实例。 2. 如果尚未加载过此,则将请求转发至其父级类加载器进行处理。这一操作会一直向上递归直到到达顶层的 Bootstrap ClassLoader。 3. 若所有上级都无法找到目标,则当前类加载器才开始查找并加载所需的文件。 上述行为可以用如下伪代码表示: ```java protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // Step 1: Check if the class has already been loaded. Class<?> c = findLoadedClass(name); if (c == null) { try { // Step 2: Delegate to parent loader first. if (parent != null) { c = parent.loadClass(name, false); } else { // If no parent exists, delegate to bootstrap loader. c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) {} // Step 3: Only attempt self-loading when delegation fails. if (c == null) { c = findClass(name); // Custom implementation of finding classes. } } // Optional step: Resolve links between classes after loading is complete. if (resolve) { resolveClass(c); } return c; } ``` --- ### 自定义类加载器与破坏双亲委派模型 尽管双亲委派模型具有诸多优点,但在某些情况下可能并不适用。比如 Web 应用服务器需要支持模块化部署、插件系统等复杂场景时,就需要打破默认的行为模式。此时可通过重新编写 `loadClass()` 方法来自定义加载策略。 一种常见的做法是在必要条件下优先让子类加载器完成加载任务后再考虑调用父类加载器。这种方式虽然解决了灵活性不足的问题,但也增加了潜在风险,例如可能导致不同版本冲突等问题。 --- ### 总结 综上所述,Java 的类加载器体系基于严格的分层架构运行,而双亲委派模型作为其核心理念之一,不仅简化了管理还增强了系统的安全性与稳定性。然而随着技术发展,针对特殊情况也出现了相应的变通方案以适应更广泛的需求。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值