ClassLoader总结

本文详细介绍了Java类加载器(ClassLoader)的工作原理及其在Java安全沙箱模型中的作用。通过分析双亲委派模型(Parent Delegation Model)的实现机制,解释了如何避免类的重复加载及保护Java核心API的安全性。

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

ClassLoader概述

作用:

类加载器抽象类,用于运行时动态加载类文件。

特性:


  1. 每个ClassLoader都维护了一份自己的名称空间, 同一个名称空间里不能出现两个同名的类。同一个类文件被两个ClassLoader则被认为是两个类型。
  2. 每一个ClassLoader实例中保存了一个父ClasLoader的引用(BootstrapClassLoader除外)。
  3. 为了实现java安全沙箱模型顶层的类加载器安全机制, java默认采用了 双亲委派模型(Parent Delegation Model)

为什么使用双亲委派机制: 因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义的类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时就被引导类加载器(Bootstrcp ClassLoader)加载,所以用户自定义的ClassLoader永远也无法加载一个自己写的String,除非你改变JDK中ClassLoader搜索类的默认算法1

核心方法:

Class<?> loadClass(String name);
Class<?> findLoadedClass(String name);
Class<?> findClass(String name);
Class<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain);

注意: 抽象类ClassLoader的方法loadClass实现了双亲委派机制,如果没有特殊需求则不建议重写,但该类中findClass方法并未实现。所以,如果需要继承ClassLoader抽象类来实现自定义的类加载器,则需要重写findClass方法。

双亲委托模型:

从ClassLoader抽象类的loadClass方法的源码(jdk1.70_67版本)可以一窥一二:

//检查类是否已经被加载
Class c = findLoadedClass(name);
if (c == null) {
    try {
        if (parent != null) {
            //如果父类加载器存在,则调用父ClassLoader进行加载,实际会是一个不断调用父类加载器的过程
            c = parent.loadClass(name, false);
        } else {
            //如果父类加载器不存在,则使用BootstrapClassLoader进行加载
            c = findBootstrapClassOrNull(name);
        }
    } catch (ClassNotFoundException e) {
        // ClassNotFoundException thrown if class not found
        // from the non-null parent class loader
    }

    if (c == null) {
        // 如果仍然没有找到,则调用自己的findClass方法进行加载,还是无法找到则会抛出ClassNotFound异常
        c = findClass(name);
    }
}

最终负责加载Class到jvm中的是defineClass方法,其内部则是调用了相应的Native方法。

综上分析,默认情况下双亲委托的加载流程(除BootstrapClassLoader和自定义的ClassLoader)如下2 :

当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。

java中的类加载体系

BootstrapClassLoader

启动类加载器是Java类加载层次中最顶层的类加载器,负责加载JDK的核心类库,如:rt.jar、resources.jar、charsets.jar等3

ExtClassLoader

扩展类加载器,负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar。其父加载器为BootstrapClassLoader。

AppClassLoader

应用类加载器,主要加载classpath目录下的所有jar和class文件。其父加载器为sun.misc.Launcher$ExtClassLoader。

其中,AppClassLoader和ExtClassLoader均继承自URLClassLoader。

注意4

除了Java默认提供的三个ClassLoader之外,用户还可以根据需要定义自已的ClassLoader,而这些自定义的ClassLoader都必须继承自java.lang.ClassLoader类,也包括Java提供的另外二个ClassLoader(Extension ClassLoader和App ClassLoader)在内,但是Bootstrap ClassLoader不继承自ClassLoader,因为它不是一个普通的Java类,底层由C++编写,已嵌入到了JVM内核当中,当JVM启动后,Bootstrap ClassLoader也随着启动,负责加载完核心类库后,并构造Extension ClassLoader和App ClassLoader类加载


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值