Tomcat源码分析(二)Bootstrap启动类分析
目录
上一章,我们下载源码,并启动了源码,Tomcat源码分析(一)启动Tomcat源码 。
现在,我们来看看Bootstrap启动类做了些什么工作。
上一章,我们下载源码,并启动了源码,Tomcat源码分析(一)启动Tomcat源码 。
现在,我们来看看Bootstrap启动类做了些什么工作。
静态代码块
设置了catelina.home和catalina.base
点击查看代码
static { // Will always be non-null // 当前工作目录的路径,总是不会为null String userDir = System.getProperty(user.dir); // Home first 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; // 设置了catelina.home 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; } // 设置了catalina.base System.setProperty(Constants.CATALINA_BASE_PROP, catalinaBaseFile.getPath()); }
main()方法
1.加锁新建一个Bootstrap对象,调用init初始化并且赋值给了私有静态对象daemon 2.调用了daemon对象load和start方法,而load和start方法里面利用了反射调用了catalinaDeamon的load和start方法
点击查看代码
/** * Main method and entry point when starting Tomcat via the provided * scripts. * * @param args Command line arguments to be processed */ 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); } } try { String command = start; if (args.length > 0) { command = args[args.length - 1]; } if (command.equals(startd)) { args[args.length - 1] = start; daemon.load(args); daemon.start(); } else if (command.equals(stopd)) { args[args.length - 1] = stop; daemon.stop(); } else if (command.equals(start)) { daemon.setAwait(true); daemon.load(args); daemon.start(); if (null == daemon.getServer()) { System.exit(1); } } else if (command.equals(stop)) { daemon.stopServer(args); } else if (command.equals(configtest)) { daemon.load(args); if (null == daemon.getServer()) { System.exit(1); } System.exit(0); } else { log.warn(Bootstrap: command \ + command + \ does not exist.); } } catch (Throwable t) { // Unwrap the Exception for clearer error reporting if (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } handleThrowable(t); t.printStackTrace(); System.exit(1); } }
init()方法
1.使用initClassLoaders()创建了commonLoader、catalinaLoader和sharedLoader 2.利用反射新建一个org.apache.catalina.startup.Catalina类对象,赋值给了catalinaDeamon。
点击查看代码
/** * Initialize daemon. * @throws Exception Fatal initialization error */ public void init() throws Exception { initClassLoaders(); Thread.currentThread().setContextClassLoader(catalinaLoader); SecurityClassLoad.securityClassLoad(catalinaLoader); // Load our startup class and call its process() method // 加载启动类并调用其process()方法 if (log.isDebugEnabled()) { log.debug(Loading startup class); } Class<?> startupClass = catalinaLoader.loadClass(org.apache.catalina.startup.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); 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); sharedLoader = createClassLoader(shared, commonLoader); } catch (Throwable t) { handleThrowable(t); log.error(Class loader creation threw exception, t); System.exit(1); } }
load()方法
通过反射调用catalinaDaemon的load()方法
点击查看代码
/** * Load daemon. */ private void load(String[] arguments) throws Exception { // Call the load() method String methodName = load; Object param[]; Class<?> paramTypes[]; if (arguments==null || arguments.length==0) { paramTypes = null; param = null; } else { paramTypes = new Class[1]; paramTypes[0] = arguments.getClass(); param = new Object[1]; param[0] = arguments; } Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes); if (log.isDebugEnabled()) { log.debug(Calling startup class + method); } method.invoke(catalinaDaemon, param); }
start()方法
通过反射调用catalinaDaemon的start()方法
点击查看代码
/** * Start the Catalina daemon. * @throws Exception Fatal start error */ public void start() throws Exception { if (catalinaDaemon == null) { init(); } Method method = catalinaDaemon.getClass().getMethod(start, (Class [])null); method.invoke(catalinaDaemon, (Object [])null); }