1. 执行Bootstrap类的static代码块, 初始化Bootstrap的catalinaHomeFile属性和catalinaBaseFile属性, 默认情况下值都为tomcat的安装目录. 关于这两个属性, 说明如下.
================================================== Advanced Configuration - Multiple Tomcat Instances ================================================== In many circumstances, it is desirable to have a single copy of a Tomcat binary distribution shared among multiple users on the same server. To make this possible, you can set the CATALINA_BASE environment variable to the directory that contains the files for your ‘personal‘ Tomcat instance. When running with a separate CATALINA_HOME and CATALINA_BASE, the files and directories are split as following: In CATALINA_BASE: * bin - Only the following files: * setenv.sh (*nix) or setenv.bat (Windows), * tomcat-juli.jar The setenv scripts were described above. The tomcat-juli library is documented in the Logging chapter in the User Guide. * conf - Server configuration files (including server.xml) * lib - Libraries and classes, as explained below * logs - Log and output files * webapps - Automatically loaded web applications * work - Temporary working directories for web applications * temp - Directory used by the JVM for temporary files (java.io.tmpdir) In CATALINA_HOME: * bin - Startup and shutdown scripts The following files will be used only if they are absent in CATALINA_BASE/bin: setenv.sh (*nix), setenv.bat (Windows), tomcat-juli.jar * lib - Libraries and classes, as explained below * endorsed - Libraries that override standard "Endorsed Standards" libraries provided by JRE. See Classloading documentation in the User Guide for details. By default this "endorsed" directory is absent. In the default configuration the JAR libraries and classes both in CATALINA_BASE/lib and in CATALINA_HOME/lib will be added to the common classpath, but the ones in CATALINA_BASE will be added first and thus will be searched first. The idea is that you may leave the standard Tomcat libraries in CATALINA_HOME/lib and add other ones such as database drivers into CATALINA_BASE/lib. In general it is advised to never share libraries between web applications, but put them into WEB-INF/lib directories inside the applications. See Classloading documentation in the User Guide for details. It might be useful to note that the values of CATALINA_HOME and CATALINA_BASE can be referenced in the XML configuration files processed by Tomcat as ${catalina.home} and ${catalina.base} respectively. For example, the standard manager web application can be kept in CATALINA_HOME/webapps/manager and loaded into CATALINA_BASE by using the following trick: * Copy the CATALINA_HOME/webapps/manager/META-INF/context.xml file as CATALINA_BASE/conf/Catalina/localhost/manager.xml * Add docBase attribute as shown below. The file will look like the following: <?xml version="1.0" encoding="UTF-8"?> <Context docBase="${catalina.home}/webapps/manager" antiResourceLocking="false" privileged="true" > <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.0\.0\.1" /> </Context> See Deployer chapter in User Guide and Context and Host chapters in the Configuration Reference for more information on contexts and web application deployment.
区分这两个属性主要是为了支持Tomcat的多实例功能.
home属性主要包含: bin(主要包含启动停止脚本), lib(公用jar包), endorsed(要覆盖JRE的jar).
base属性主要包含 : bin(只能包含setevn(设置JRE_HOME等环境变量), tomcat-juli.jar(日志相关)文件), conf, logs, webapps, work, temp, lib(该tomcat实例下所有web应用共享的jar,tomcat加载时,会先加载这里的jar再加载home/lib下的jar).
2. 如果daemon属性为null, 就创建一个Bootstrap实例,并调用Bootstrap.init()方法初始化, 否则设置当前线程类加载器为daemon.catalinaLoader(另外线程调用Bootstrap.main(‘stop‘)方法).
3. Bootstrap.init()方法逻辑, 首先初始化三个类加载器initClassLoaders().
commonLoader: 根据common.loader属性的配置(catalina.properties), 创建对应的类加载器, 默认情况下顺序加载 ${catalina.base}/lib, ${catalina.base}/lib/*.jar, ${catalina.home}/lib, ${catalina.home}/lib/*.jar 四个目录下的class和jar.
catalinaLoader: 根据server.loader属性的配置, 创建对应的类加载器,其父类加载其为commonLoader, 默认server.loader属性为空, 则直接使用commonLoader.
sharedLoader:根据shared.loader属性配置,创建对应的类加载器,其父类加载其为commonLoader, 默认shared.loader属性为空, 则直接使用commonLoader.
4. 初始化完类加载器后, 设置当前线程上下文类加载器为 catalinaLoader 类加载器, 既commonLoader类加载器. Thread.currentThread().setContextClassLoader(catalinaLoader)
5. 如果当前有SecurityManager, 则提前加载一些类, 防止出现AccessControlException异常. SecurityClassLoad.securityClassLoad(catalinaLoader)
6. 使用catalinaLoader加载org.apache.catalina.startup.Catalina类, 创建实例(Catalina构造方法会配置安全属性,如果有安全管理器), 并反射调用setParentClassLoader(sharedLoader), 设置Catalina实例的parentClassLoader属性为sharedLoader类加载器.
7. 设置daemon为新创建的实例.
8. 进入start命令逻辑. 反射调用Catalina.setAwait(true), 主要是为了启动完成后, 阻塞main线程, 监听某一端口, 等待shutdown命令到来(Catalina.start(), Catalina.await()). 如果不设置, 则main线程执行完, 直接退出.
9. 反射调用Catalina.load(arg[])方法, 可以通过启动参数设置server.xml文件位置, 设置是否启用naming, 然后调用Catalina.load().
10. Catalina.load()逻辑, 首先初始化temp目录, 然后初始化naming需要的一些系统属性(org.apache.naming.java.javaURLContextFactory), 然后获取server.xml配置文件, 创建Digester实例, 开始解析server.xml配置文件.
11. Digester具体的解析方式见 xxxxxxxxxxxxxxxxxxxxxxxxx.
12. 双休关联StandardServer和Catalina实例, 并设置server的catalinaHome和catalinaBase属性.
13. 包装System.out和in流为SystemLogHandler.
14. 启动server, getServer().init().