[tomcat7源码学习]初始化之ClassLoader

初始化之ClassLoader

初始化第2步就是ClassLoader,调用的initClassLoaders()apache

private void initClassLoaders() {
    try {
        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);
    }
}

一共有3个ClassLoader,分别为commonLoader,catalinaLoader,sharedLoader,都是经过调用createClassLoader 来获取。tomcat

private ClassLoader createClassLoader(String name, ClassLoader parent)
        throws Exception {

    String value = CatalinaProperties.getProperty(name + ".loader");
    if ((value == null) || (value.equals("")))
        return parent;

    value = replace(value);

    List<Repository> repositories = new ArrayList<Repository>();

    StringTokenizer tokenizer = new StringTokenizer(value, ",");
    while (tokenizer.hasMoreElements()) {
        String repository = tokenizer.nextToken().trim();
        if (repository.length() == 0) {
            continue;
        }

        // Check for a JAR URL repository
        try {
            @SuppressWarnings("unused")
            URL url = new URL(repository);
            repositories.add(
                    new Repository(repository, RepositoryType.URL));
            continue;
        } catch (MalformedURLException e) {
            // Ignore
        }

        // Local repository
        if (repository.endsWith("*.jar")) {
            repository = repository.substring
                (0, repository.length() - "*.jar".length());
            repositories.add(
                    new Repository(repository, RepositoryType.GLOB));
        } else if (repository.endsWith(".jar")) {
            repositories.add(
                    new Repository(repository, RepositoryType.JAR));
        } else {
            repositories.add(
                    new Repository(repository, RepositoryType.DIR));
        }
    }

    ClassLoader classLoader = ClassLoaderFactory.createClassLoader
        (repositories, parent);

    // Retrieving MBean server
    MBeanServer mBeanServer = null;
    if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
        mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
    } else {
        mBeanServer = ManagementFactory.getPlatformMBeanServer();
    }

    // Register the server classloader
    ObjectName objectName =
        new ObjectName("Catalina:type=ServerClassLoader,name=" + name);
    mBeanServer.registerMBean(classLoader, objectName);

    return classLoader;

}

###createClassLoader###ide

1.首先从配置文件中取出相应的loader,若是没有就返回父Loader,取配置文件的优先级为(参考类CatalinaProperties):this

1.从System中获取catalina.configurl

2.从catalina.base下面的conf文件夹里面获取catalina.properties文件(通常状况下默认的就为这个)code

3.包路径/org/apache/catalina/startup/catalina.propertiesorm

2.通常状况下在咱们的${catalina.base}/conf/catalina.properties中默认都有配置server

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

server.loadershared.loader都为空,因此默认状况下这两个loader都为common.loader继承

3.把从配置中取出的路径所有加到一个List<Repository>,每个Repository都包含一个路径,而且会指明其类型,类型包括有:token

public static enum RepositoryType {
    DIR,
    GLOB,
    JAR,
    URL
}

4.在取出全部路径后,经过ClassLoaderFactory.createClassLoader来获取classLoader,在ClassLoaderFactory.createClassLoader中解析完全部路径后,经过

return AccessController.doPrivileged(
    new PrivilegedAction<StandardClassLoader>() {
        @Override
        public StandardClassLoader run() {
            if (parent == null)
                return new StandardClassLoader(array);
            else
                return new StandardClassLoader(array, parent);
        }
    });

返回ClassLoader,因此tomcat里面的ClassLoader就为StandardClassLoader,这个又继承的URLClassLoader

5.把ClassLoader注册到MBeanServer

###总结###

1.tomcat中默认加载jar的顺序为${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,而且里面用的LinkedHashSet来保存的这些路径,因此当咱们有多个instance的时候,${catalina.base}应该会覆盖${catalina.home}里面一样的,以及若是有些公共的jar,须要提早加载的也应该能够配置到这里

2.看了StandardClassLoader,在开发过程当中咱们应该也能够动态加载jar。直接使用URLClassLoader加载

相关文章
相关标签/搜索