代碼片段:
org.apache.catalina.startup.Bootstrap#main()
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; }
Bootstrap static {}
Bootstrap有一個靜態代碼塊, 用來獲取tomcat的作業目錄和安裝目錄.
默認情況下, 是作業目錄和安裝目錄是相同的, 也可以配置成不同的.
// 這里有一個靜態代碼塊 static { // Will always be non-null // 獲取用戶目錄 String userDir = System.getProperty("user.dir"); // Home first // tomcat的安裝目錄 String home = System.getProperty(Constants.CATALINA_HOME_PROP); File homeFile = null; if (home != null) { File f = new File(home); try { homeFile = f.getCanonicalFile(); } catch (IOException ioe) { homeFile = f.getAbsoluteFile(); } } if (homeFile == null) { // First fall-back. See if current directory is a bin directory // in a normal Tomcat install File bootstrapJar = new File(userDir, "bootstrap.jar"); if (bootstrapJar.exists()) { File f = new File(userDir, ".."); try { homeFile = f.getCanonicalFile(); } catch (IOException ioe) { homeFile = f.getAbsoluteFile(); } } } if (homeFile == null) { // Second fall-back. Use current directory File f = new File(userDir); try { homeFile = f.getCanonicalFile(); } catch (IOException ioe) { homeFile = f.getAbsoluteFile(); } } catalinaHomeFile = homeFile; System.setProperty(Constants.CATALINA_HOME_PROP, catalinaHomeFile.getPath()); // Then base String base = System.getProperty(Constants.CATALINA_BASE_PROP); if (base == null) { // 一般情況下, 作業目錄 = 安裝目錄 catalinaBaseFile = catalinaHomeFile; } else { File baseFile = new File(base); try { baseFile = baseFile.getCanonicalFile(); } catch (IOException ioe) { baseFile = baseFile.getAbsoluteFile(); } catalinaBaseFile = baseFile; } System.setProperty(Constants.CATALINA_BASE_PROP, catalinaBaseFile.getPath()); }
bootstrap.init()
public void init() throws Exception { // 創建了三個自己的類加載器 // commonLoader catalinaLoader sharedLoader initClassLoaders(); Thread.currentThread().setContextClassLoader(catalinaLoader); SecurityClassLoad.securityClassLoad(catalinaLoader); // Load our startup class and call its process() method if (log.isDebugEnabled()) log.debug("Loading startup class"); // 反射加載類: Catalina Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina"); // 反射創建 Catalina Object startupInstance = startupClass.getConstructor().newInstance(); // Set the shared extensions class loader if (log.isDebugEnabled()) log.debug("Setting startup class properties"); String methodName = "setParentClassLoader"; Class<?> paramTypes[] = new Class[1]; paramTypes[0] = Class.forName("java.lang.ClassLoader"); Object paramValues[] = new Object[1]; paramValues[0] = sharedLoader; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); // 呼叫 Catalina#setParentClassLoader(sharedLoader), 設定屬性 // Catalina.parentClassLoader method.invoke(startupInstance, paramValues); catalinaDaemon = startupInstance; }
initClassLoaders
/** * 創建了三個自己的類加載器 commonLoader catalinaLoader sharedLoader */ 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); // 給 webapp 用 sharedLoader = createClassLoader("shared", commonLoader); } catch (Throwable t) { handleThrowable(t); log.error("Class loader creation threw exception", t); System.exit(1); } }
創建的三個類加載器并不是三個獨立的類加載器, 其結構關系為:

setParentClassLoader
//org.apache.catalina.startup.Catalina#setParentClassLoader public void setParentClassLoader(ClassLoader parentClassLoader) { this.parentClassLoader = parentClassLoader; }
tomcat 初始化時, 代碼邏輯還是比較簡單的.
主要干了兩件事:
1. 呼叫 initClassLoaders() , 創建了三個自己的類加載器
2. 反射創建了 Catalina 類, 并呼叫了其 setParentClassLoader() 方法, 將 sharedLoader 類加載器設定進去
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/56951.html
標籤:Java
