[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加載

相關文章
相關標籤/搜索