Tomcat ClassLoader打破双亲委派源码解析

 更新时间:2023年09月01日 11:31:34   作者:汤卜  
这篇文章主要为大家介绍了Tomcat ClassLoader打破双亲委派源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

java加载类

java加载类的时候需要使用类加载器,开发人员可以定制类的加载器,比如tomcat就扩展了自己的类加载器。这篇文章结合代码研究一下jdk类的加载器和tomcat的类加载

先上图复习一下

来看一下jdk的ClassLoader的代码

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 本类加载器从缓存里面拿取已经加载过的ClassLoader
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    // 父类为BootStrapClassLoader的classLoader 的parent变量为空
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
                ..........
    }

注意看一下核心代码,实际上parent只要不为空就由parent来加载,因此当类未加载的时候,总是由上级来优先加载。

tomcat的类加载

首先来看一下tomcat的类加载器,tomcat写了一个自己的类加载器,看下基类WebappClassLoaderBase的实现

@Override
    public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
           ................
            // 从缓存里面取,不影响加载顺序,请着重忽略
            clazz = findLoadedClass0(name);
            ..........
            clazz = findLoadedClass(name);
            .........
           /**
     * The bootstrap class loader used to load the JavaSE classes. In some
     * implementations this class loader is always <code>null</code> and in
     * those cases {@link ClassLoader#getParent()} will be called recursively on
     * the system class loader and the last non-null result used.
     */
            // 注意看注释,javaseLoader是bootstrap加载的,所以javaseLoader是扩展类加载器
            ClassLoader javaseLoader = getJavaseClassLoader();
            clazz = javaseLoader.loadClass(name);
            boolean delegateLoad = delegate || filter(name, true);
            // (2) Search local repositories
            if (log.isDebugEnabled()) {
                log.debug("  Searching local repositories");
            }
            try {
            // 重写了findClass方法,从项目中的lib和class里加载
                clazz = findClass(name);
                if (clazz != null) {
                    if (log.isDebugEnabled()) {
                        log.debug("  Loading class from local repository");
                    }
                    if (resolve) {
                        resolveClass(clazz);
                    }
                    return clazz;
                }
            } catch (ClassNotFoundException e) {
                // Ignore
            }
            // (3) Delegate to parent unconditionally
            if (!delegateLoad) {
                if (log.isDebugEnabled()) {
                    log.debug("  Delegating to parent classloader at end: " + parent);
                }
                try {
//  继承于SystemClassLoader该类,所以这个parent是SystemClassLoader,
                    clazz = Class.forName(name, false, parent);
                    if (clazz != null) {
                        if (log.isDebugEnabled()) {
                            log.debug("  Loading class from parent");
                        }
                        if (resolve) {
                            resolveClass(clazz);
                        }
                        return clazz;
                    }
                } catch (ClassNotFoundException e) {
                    // Ignore
                }
            }
        }
        throw new ClassNotFoundException(name);
    }

把顺序相关外的代码省略了,注意看注释。

因此来梳理一下加载顺序

1.找ext加载器,ext会优先走BootStrap加载器,加载java核心类库

2.ext加载不到就去走重写的findClass,走web项目的lib包和class目录,加载项目的class

3.重写的findClass找不到,就去系统类加载器SystemClassLoader来加载。

tomcat为什么要重写这个ClassLoader呢

1.最重要的就是做隔离性,不同的 web包引入不同的jar包版本,如果重写类的加载顺序,统一走SystemClassloader加载,那么只会加载一个类在内存,另外一个版本的class永远也不会加载进内存。无法实现web项目的隔离

2.可以针对一个应用进行重新部署,一个应用一个加载器,需要重新部署,就把这个classLoader加载的类重新加载就可以了

所以看起来打破双亲委派这种大名头的知识,看一下源码就清晰了,养成阅读源码习惯就可以

以上就是Tomcat ClassLoader打破双亲委派源码解析的详细内容,更多关于Tomcat ClassLoader双亲委派的资料请关注脚本之家其它相关文章!

相关文章

  • 一文解读java.nio.ByteBuffer

    一文解读java.nio.ByteBuffer

    这篇文章主要介绍了java.nio.ByteBuffer的用法解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • Java实现快速生成词云图的示例代码

    Java实现快速生成词云图的示例代码

    词云(Word Cloud),又称文字云、标签云(Tag Cloud)、关键词云(Keyword Cloud),是对文本信息中一定数量的关键词出现的频率高低情况的一种可视化展现方式。本文将用Java代码实现快速生成词云图,需要的可以参考一下
    2023-02-02
  • JUC三大辅助类CountDownLatch、CyclicBarrier和Semaphore详解

    JUC三大辅助类CountDownLatch、CyclicBarrier和Semaphore详解

    这篇文章主要介绍了JUC三大辅助类CountDownLatch、CyclicBarrier和Semaphore详解,CountDownLatch 类可以设置一个计数器,然后通过 countDown 方法来进行 减 1 的操作,使用 await 方法等待计数器不大于 0,然后继续执行 await 方法 之后的语句,需要的朋友可以参考下
    2024-01-01
  • SpringBoot集成Redis及Redis使用方法

    SpringBoot集成Redis及Redis使用方法

    Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,这篇文章主要介绍了SpringBoot集成Redis及Redis使用方法,需要的朋友可以参考下
    2023-08-08
  • Servlet和Spring MVC的区别及使用说明

    Servlet和Spring MVC的区别及使用说明

    这篇文章详细介绍了Servlet和SpringMVC的基本概念、工作原理、功能对比和应用场景,Servlet是JavaWeb开发的基础,而SpringMVC是一个基于Servlet的高级框架,提供了更强大的功能和易用性,文章通过定义、原理和示例代码,帮助读者理解这两个技术的区别与联系
    2025-01-01
  • Java Spring的两种事务你知道吗

    Java Spring的两种事务你知道吗

    这篇文章主要为大家详细介绍了Java Spring的两种事务,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • Java泛型类与泛型方法的定义详解

    Java泛型类与泛型方法的定义详解

    这篇文章主要介绍了Java泛型类与泛型方法的定义,结合实例形式详细分析了java泛型类与泛型方法定义、用法及相关操作注意事项,需要的朋友可以参考下
    2019-08-08
  • Java调用pyzbar解析base64二维码过程解析

    Java调用pyzbar解析base64二维码过程解析

    这篇文章主要介绍了Java调用pyzbar解析base64二维码过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • SpringBoot实现文件在线预览功能的全过程

    SpringBoot实现文件在线预览功能的全过程

    我们开发业务系统的时候,经常有那种文档文件在线预览的需求,下面这篇文章主要给大家介绍了关于SpringBoot实现文件在线预览功能的相关资料,需要的朋友可以参考下
    2021-11-11
  • 使用Criteria进行分组求和、排序、模糊查询的实例

    使用Criteria进行分组求和、排序、模糊查询的实例

    这篇文章主要介绍了使用Criteria进行分组求和、排序、模糊查询的实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论