③. ClassLoader的创建
- ①. 加载器类图:
②. 先从 BootStrap 的main方法看起:
可以看到这里先判断了bootstrap是否为null,如果不为null直接把
CatalinaClassLoader设置到了当前线程,如果为null下面是走到了init()方法
public static void main(String args[]) { synchronized (daemonLock) { if (daemon == null) { // Don't set daemon until init() has completed Bootstrap bootstrap = new Bootstrap(); try { bootstrap.init(); } catch (Throwable t) { handleThrowable(t); t.printStackTrace(); return; } daemon = bootstrap; } else { // When running as a service the call to stop will be on a new // thread so make sure the correct class loader is used to // prevent a range of class not found exceptions. Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); } // 省略其余代码... } }
③. 接着这里看到了会调用 initClassLoaders() 方法进行类加载器的初始化,初始化完成后,同样会设置 Catalina ClassLoader到当前线程
public void init() throws Exception { // 初始化类加载器 initClassLoaders(); // 设置线程类加载器,将容器的加载器传入 Thread.currentThread().setContextClassLoader(catalinaLoader); // 设置区安全类加载器 SecurityClassLoad.securityClassLoad(catalinaLoader); // 省略其余代码... }
④ .看到这里应该就清楚了,会创建三个ClassLoader:CommClassLoader,CatalinaClassLoader,SharedCla ssLoader,正好对应前面介绍的三个基础类加载器
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); } }
⑤. 接着进入createClassLoader() 查看代码:
可以看到,这里加载的资源正好是我们刚才看到的配置文件conf/catalina.properties 中的 common.loader ,server.loader 和 shared.loader
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<>(); String[] repositoryPaths = getPaths(value); for (String repository : repositoryPaths) { // 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)); } } return ClassLoaderFactory.createClassLoader(repositories, parent); }