前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >细说tomcat之类加载器

细说tomcat之类加载器

作者头像
编程随笔
发布2019-09-11 15:47:58
1K0
发布2019-09-11 15:47:58
举报
文章被收录于专栏:后端开发随笔

官网:http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html Java类加载与Tomcat类加载器层级关系对比

代码语言:javascript
复制
Java ClassLoader:                         
    Bootstrap ClassLoader(加载$JAVA_HOME/jre/lib/目录下核心类库:resources.jar,rt.jar,sunrsasign.jar,jsse.jar,jce.jar,charsets.jar,jfr.jar,以及jre/classes目录下的class)                 
       /|\
        |                                                            Tomcat ClassLoader:      
    ExtClassLoader(加载$JAVA_HOME/jre/lib/ext/目下的所有jar) -------- Bootstrap(加载$JAVA_HOME/jre/lib/ext/目录下的所有jar)
       /|\                                                                 /|\
        |                                                                   |     
    AppClassLoader(加载应用程序classpath目录下的所有jar和class文件)    System(加载$CATALINA_HOME/bin/bootstrap.jar,$CATALINA_BASE/bin/tomcat-juli.jar,$CATALINA_HOME/bin/commons-daemon.jar)
                                                                           /|\
                                                                            |
                                                                         Common(加载$CATALINA_BASE/lib和$CATALINA_HOME/lib下的class,资源和jar文件)
                                                                           /|\
                                                                            |
                                                                         WebAppClassLoader(加载WebApp/WEB-INF/classes,WebApp/WEB-INF/lib)

Java ClassLoader验证:

代码语言:javascript
复制
public class ClassLoaderTest {
    public static void main(String[] args) {
        ClassLoader appClassLoader = ClassLoaderTest.class.getClassLoader();
        ClassLoader extClassLoader = appClassLoader.getParent();
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(appClassLoader);
        System.out.println(extClassLoader);
        System.out.println(bootstrapClassLoader);
    }
}

Tomcat ClassLoader验证:

代码语言:javascript
复制
public class ClassLoaderServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ClassLoader loader = this.getClass().getClassLoader();
        while(loader != null) {
            System.out.println(loader);
            loader = loader.getParent();
        }
        System.out.println(loader);
    }
}

输出:
ParallelWebappClassLoader
  context: test-web
  delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@379619aa

java.net.URLClassLoader@379619aa
sun.misc.Launcher$AppClassLoader@764c12b6
sun.misc.Launcher$ExtClassLoader@1a93a7ca
null

跟踪org.apache.catalina.loader.ParallelWebappClassLoader源码发现,org.apache.catalina.loader.WebappClassLoaderBase重写了toString()方法:

代码语言:javascript
复制
@Override
public String toString() {

    StringBuilder sb = new StringBuilder(this.getClass().getSimpleName());
    sb.append("\r\n  context: ");
    sb.append(getContextName());
    sb.append("\r\n  delegate: ");
    sb.append(delegate);
    sb.append("\r\n");
    if (this.parent != null) {
        sb.append("----------> Parent Classloader:\r\n");
        sb.append(this.parent.toString());
        sb.append("\r\n");
    }
    if (this.transformers.size() > 0) {
        sb.append("----------> Class file transformers:\r\n");
        for (ClassFileTransformer transformer : this.transformers) {
            sb.append(transformer).append("\r\n");
        }
    }
    return (sb.toString());
}

也就是说,Tomcat的ClassLoader结构为:

代码语言:javascript
复制
null(JVM Bootstrap ClassLoader)
sun.misc.Launcher$ExtClassLoader@1a93a7ca
sun.misc.Launcher$AppClassLoader@764c12b6
java.net.URLClassLoader@379619aa
org.apache.catalina.loader.ParallelWebappClassLoader

Tomcat Common ClassLoader默认的搜索顺序为:

代码语言:javascript
复制
(1)unpacked classes and resources in $CATALINA_BASE/lib
(2)JAR files in $CATALINA_BASE/lib
(3)unpacked classes and resources in $CATALINA_HOME/lib
(4)JAR files in $CATALINA_HOME/lib

Tomcat classloader类图

总结: 1. Java装载类使用“全盘负责委托机制”。 “全盘负责”是指当一个ClassLoder装载一个类时,除非显示地使用另外一个ClassLoder,否则该类所依赖及引用的类也由这个ClassLoder载入; “委托机制”是指先委托父类装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类。 2. Tomcat的WebAppClassLoade默认不使用“委托机制”,查找class和资源的顺序如下:

代码语言:javascript
复制
(1)Bootstrap classes of your JVM
(2)/WEB-INF/classes of your web application
(3)/WEB-INF/lib/*.jar of your web application
(4)System class loader classes
(5)Common class loader classes
If the web application class loader is configured with <Loader delegate="true"/> then the order becomes:
(1)Bootstrap classes of your JVM
(2)System class loader classes
(3)Common class loader classes
(4)/WEB-INF/classes of your web application
(5)/WEB-INF/lib/*.jar of your web application

3. Tomcat中变量CATALINA_BASE和CATALINA_HOME的含义

代码语言:javascript
复制
Throughout the docs, you'll notice there are numerous references to $CATALINA_HOME的含义.
This represents the root of your Tomcat installation. When we say, "This information can be found in your $CATALINA_HOME/README.txt file" we mean to look at the README.txt file at the root of your Tomcat install.
Optionally, Tomcat may be configured for multiple instances by defining $CATALINA_BASE for each instance. If multiple instances are not configured, $CATALINA_BASE is the same as $CATALINA_HOME.

一言以蔽之:如果没有明确设置CATALINA_BASE变量,则CATALINA_BASE与CATALINA_HOME值相同,都是值tomcat安装目录。

【参考】 http://www.hollischuang.com/archives/199 深度分析Java的ClassLoader机制(源码级别) http://blog.csdn.net/xyang81/article/details/7292380 深入分析Java ClassLoader原理

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-06-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档