初始化第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
加载