初始化第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.loader
和shared.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
加載