tomcat中的类加载机制

Tomcat中的类加载机制符合JVM推荐的双亲委派模型,关于JVM的类加载机制不多说,网上很多资料。

1. Tomcat类加载器过程。

tomcat启动初始化阶段创建几个类加载器:

    private void initClassLoaders() {
        try {
            //aaa
            commonLoader = createClassLoader("common", null);
            if( commonLoader == null ) {
                // no config file, default to this loader - we might be in a 'single' env.
                commonLoader=this.getClass().getClassLoader();
            }
            catalinaLoader = createClassLoader("server", commonLoader);
            sharedLoader = createClassLoader("shared", commonLoader);
        } catch (Throwable t) {
            handleThrowable(t);
            log.error("Class loader creation threw exception", t);
            System.exit(1);
        }
    }

Bootstrap启动时创建三个URLClassLoader :  common , catalina, shared

接下来:

        initClassLoaders();

        Thread.currentThread().setContextClassLoader(catalinaLoader);

        SecurityClassLoad.securityClassLoad(catalinaLoader);

        // Load our startup class and call its process() method
        if (log.isDebugEnabled())
            log.debug("Loading startup class");
        Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.newInstance();

        // Set the shared extensions class loader
        if (log.isDebugEnabled())
            log.debug("Setting startup class properties");
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);

红色部分的代码 是将 Catalina 对象的父类加载器设置为 shared 加载器。之后,在Tomcat其他组件(Server , Service , Container 等)获取得到的父类加载都是 shared 加载器,

当创建 WebappClassLoader(即 应用程序类加载器)时指定 的父加载器是 shared加载器,网上包括一部分讲解tomcat的书里说到应用程序类加载器 的 父加载器是 common,其实是不准确的,只是默认配置下, shared 加载器 就是 common加载器。

tomcat加载类的顺序

查看WebappClassLoaderBase.loadClass()源码,可以很清楚的了解类加载顺序:

  • 在 tomcat 已加载类的列表中查找
  • 在jvm已加载类的列表中查找
  • 尝试从JVM系统库({java.home}/jre/lib和{java.home}/jre/lib/ext)加载
  • 尝试从tomcat中的当前web应用的/WEB-INF/classes目录下加载     
  • 尝试从tomcat中的当前web应用的/WEB-INF/lib目录下加载
  • 尝试从tomcat shared指定的类库中加载
  • 尝试从tomcat common指定的类库中加载
  • 尝试使用系统类加载器(AppClassLoader)在classpath中加载(使用Class.forName()方法)

如果上述步骤都没有加载到类,就会抛出ClassNotFoundException

2. Tomcat 类库和 web应用类库的共享与隔离

有四种逻辑关系:

  •     tomcat类库与web应用隔离类库 , 由catalina类加载器来实现
  •     tomcat类库与web应用共享类库,由common类加载器来实现
  •     多个web应用共享类库,由shared类加载器来实现
  •     多个web应用隔离类库,由一个web应用对应一个唯一的应用程序类加载器来实现(WebappClassLoader)

catalina,common,shared的配置在conf/catalina.properties中

 common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar

server.loader=

shared.loader= 

 

posted @ 2017-09-14 17:36  WanderingAlbatross  阅读(218)  评论(0编辑  收藏  举报