`
flyfoxs
  • 浏览: 296836 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

细说Tomcat如何打破双亲委派(有源码和图)

 
阅读更多

一句话概况: 不考虑缓存, 那么装载路径就是,先Classpath, 然后War包,当前工程, 最后才是Tomcat相关目录. 不考虑缓存,是因为缓存只是用来加快速度,对外不调用展现出的逻辑效果是可以忽略的.

 

下图是一个概况的流程图, 简介起见,绘图过程中移除了缓存功能. (个了感觉还是有些逻辑还是有些复杂的,图画出来了,自己看着都觉得还是不清楚,但是也没发现可以改进的地方)

 



 
 

 

下面是关键的代码,已经添加了注释.

//WebappClassLoader.loadClass (Tomcat 7.0)


    @Override
    public synchronized Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException {

        if (log.isDebugEnabled())
            log.debug("loadClass(" + name + ", " + resolve + ")");
        Class<?> clazz = null;

//检查当前ClassLoad是否已经停止了
        // Log access to stopped classloader
        if (!started) {
            try {
                throw new IllegalStateException();
            } catch (IllegalStateException e) {
                log.info(sm.getString("webappClassLoader.stopped", name), e);
            }
        }
 
//检查缓存1,Class是否已经被当前Class"实例"装载过
       // (0) Check our previously loaded local class cache
        clazz = findLoadedClass0(name);
        if (clazz != null) {
            if (log.isDebugEnabled())
                log.debug(" Returning class from cache");
            if (resolve)
                resolveClass(clazz);
            return (clazz);
        }
//ClassLoader检查缓存2,Class是否已经被父类"实例"装载过
        // (0.1) Check our previously loaded class cache
        clazz = findLoadedClass(name);
        if (clazz != null) {
            if (log.isDebugEnabled())
                log.debug(" Returning class from cache");
            if (resolve)
                resolveClass(clazz);
            return (clazz);
        }

//ClassLoader装载系统classpath下面的类, 阻止webapp覆盖了J2SE的类
        // (0.2) Try loading the class with the system class loader, to prevent
        // the webapp from overriding J2SE classes
        try {
            clazz = system.loadClass(name);
            if (clazz != null) {
                if (resolve)
                    resolveClass(clazz);
                return (clazz);
            }
        } catch (ClassNotFoundException e) {
            // Ignore
        }

//安全检查
        // (0.5) Permission to access this class when using a SecurityManager
        if (securityManager != null) {
            int i = name.lastIndexOf('.');
            if (i >= 0) {
                try {
                    securityManager.checkPackageAccess(name.substring(0,i));
                } catch (SecurityException se) {
                    String error = "Security Violation, attempt to use " +
                        "Restricted Class: " + name;
                    log.info(error, se);
                    throw new ClassNotFoundException(error, se);
                }
            }
        }

//默认的返回值为false, 
//delegate = false
//filter(name) 通过一个List指定哪些package里面的Class使用双亲委派模式,但是默认这个List是空
//比如包名以Java开头的,就需要使用双亲委派模式,不过这一点"部分"由 (0.2) 在上面已经实现了
        boolean delegateLoad = delegate || filter(name);

//针对一些明确指定的package,使用双亲委派模式加载
        // (1) Delegate to our parent if requested
        if (delegateLoad) {
            if (log.isDebugEnabled())
                log.debug(" Delegating to parent classloader1 " + parent);
            ClassLoader loader = parent;
            if (loader == null)
                loader = system;
            try {
                clazz = Class.forName(name, false, loader);
                if (clazz != null) {
                    if (log.isDebugEnabled())
                        log.debug(" Loading class from parent");
                    if (resolve)
                        resolveClass(clazz);
                    return (clazz);
                }
            } catch (ClassNotFoundException e) {
                // Ignore
               //如果(1)通过双亲委派加载发生异常, 忽略异常,
            }
        }

     
        //尝试从本地加载Class( 如果(1)通过双亲委派加载发生异常, 忽略异常,也会走到这一步)
        // (2) Search local repositories
        if (log.isDebugEnabled())
            log.debug(" Searching local repositories");
        try {
            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);
            ClassLoader loader = parent;
            if (loader == null)
                loader = system;
            try {
                clazz = Class.forName(name, false, loader);
                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);

    }

 

 

 

 

 

  • 大小: 61.1 KB
0
0
分享到:
评论
1 楼 xialia8 2017-04-26  
有个疑问,WebAppContextClassLoader的parent是哪个类呢?

相关推荐

    《细说PHP》配套源码.rar

    《细说PHP》配套源码,很罕见的案例哟 /*==================================================================*/ /* 文件名:comm_pro.php */ /* 概要: 文章评论的处理页面. ...

    《细说PHP》配套源码

    《细说PHP》是一本深入浅出的PHP编程教材,旨在帮助读者全面理解PHP语言的原理和实际应用。配套源码提供了书中各个章节实例的完整代码,让学习者能够亲手实践,加深对PHP编程的理解。以下是对这些源码中涉及的知识点...

    《细说php》光盘源码

    《细说PHP》是一本深度解析PHP编程语言的书籍,其光盘源码包含了书中所有实例和示例的完整代码,对于学习和深入理解PHP有着极高的价值。这份源码的特点在于注释详尽,可以帮助读者更好地理解每段代码的功能和实现...

    《细说PHP》光盘源码

    《细说PHP》是一本广泛受到PHP初学者和进阶者欢迎的教程书籍,其光盘源码包含了大量的实例和练习,旨在帮助读者深入理解PHP编程语言的各种概念和技术。源码通常包括书中提及的示例程序、脚本以及可能的项目文件,...

    细说PHP第二版 源码

    细说PHP第二版 源码 &lt;html&gt; &lt;!-- HTML文件开始 --&gt; &lt;head&gt; &lt;!-- HTML文件的头部开始 --&gt; ... ... &lt;!-- HTML文件的头部内容 --&gt; &lt;/head&gt; &lt;!-- HTML文件的头部结束 --&gt; &lt;body&gt; &lt;!-- ...

    细说PHP配套源码

    最后,源码分析还有助于理解PHP的最佳实践和设计模式。比如,如何编写可读性强、可维护性高的代码,如何组织项目结构,以及如何使用命名空间和自动加载来简化代码管理。通过实践,你可以培养出良好的编程习惯,提升...

    《细说PHP》配套源码.zip

    而对有经验的开发者来说,这些源码则提供了复习和查找特定功能实现的好去处。 总的来说,《细说PHP》配套源码.zip是一个珍贵的学习资源,无论你是PHP新手还是有一定经验的开发者,都可以从中受益匪浅。通过逐行阅读...

    细说PHP光盘源码,《细说PHP》配套源码,php资源下载,php代码

    《细说PHP》是一本广泛受到PHP初学者和开发者欢迎的教材,它的配套源码是学习和实践PHP编程的重要资源。这本书深入浅出地讲解了PHP语言的基础知识、Web开发技术以及高级应用,旨在帮助读者从零基础快速掌握PHP编程,...

    高洛峰细说PHP第二版配套源码

    5. 错误处理和调试:源码中可能会有错误报告、异常处理和日志记录的实例,这些是提高程序健壮性的重要手段。 6. 函数库应用:PHP拥有丰富的内置函数库,如字符串处理、数组操作、文件系统操作等。通过源码,读者...

    《细说android 4.0 ndk编程》源码

    《细说Android 4.0 NDK编程》一书深入探讨了Android系统中NDK(Native Development Kit)的使用和编程技巧,旨在帮助开发者利用C和C++等原生语言来开发高性能、低级别的Android应用。NDK是Google提供的一组工具集,...

    《细说PHP》光盘源码.rar

    《细说PHP》是一本深度解析PHP编程语言的专业书籍,其光盘源码rar压缩包包含了大量的示例代码和练习项目,旨在帮助读者深入理解PHP的语法、函数库以及实际应用开发技巧。这本书覆盖了从PHP的基础知识到高级特性的全...

    细说PHP 源码

    《细说PHP》是高洛峰撰写的一本深入解析PHP编程的书籍,其配套源码提供了丰富的实例和代码示例,旨在帮助读者更好地理解和实践PHP编程。这本书涵盖了PHP的各个方面,从基础语法到高级特性,从函数应用到面向对象编程...

    细说php 4th 在线教育系统EDUPlayer源码

    细说php 4th 在线教育系统EDUPlayer源码28章 项目源码

    细说PHP源码

    《细说PHP源码》是针对PHP编程语言深入解析的一部教程,由PHP兄弟连倾情打造,旨在帮助开发者更全面、深入地理解PHP的内部工作机制,提升技术水平,努力成为PHP开发的大牛。通过学习本教程,我们可以了解到PHP源码...

    《细说PHP》的项目源码

    8. **错误处理与日志记录**:良好的错误处理机制是任何项目必备的,BroCMS可能会有错误捕获和日志记录功能,方便调试和问题排查。 9. **模板布局**:BroCMS的前端部分可能使用了HTML、CSS和JavaScript,展示动态...

    细说php中的cms项目源码(php开发cms实例参考 )

    "细说php中的cms项目源码"是一个专为初学者设计的教程,旨在帮助他们理解和学习如何使用PHP开发CMS系统。这个教程基于"细说php"的第二版,最后一章的内容,提供了实际的代码示例,方便开发者进行实践。 首先,我们...

Global site tag (gtag.js) - Google Analytics