tomcat 启动流程01
通过debug 分析tomcat启动流程
1.tomcat启动入口
2、初始化Catalina对象
1. 初始化内容:反射实例话Catalina并添加ClassLoader
初始化入口
public static void main(String args[]) {//args 参数是start, stop 等等
if (daemon == null) {
// Don't set daemon until init() has completed
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.init();//初始化Catalina对象,参考catalinaDaemon
bootstrap.init会初始化一个Catalina对象,并给其中的ClassLoader赋值
classLoader成员变量
/**
* The shared extensions class loader for this server.
*/
protected ClassLoader parentClassLoader =Catalina.class.getClassLoader();
2、初始化Catalina的classloader
//tomcat 的3个相关classloader
ClassLoader commonLoader = null;
ClassLoader catalinaLoader = null;
ClassLoader sharedLoader = null;
// -------------------------------------------------------- Private Methods
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);
上述initClassLoaders方法会读取${TOMCAT_HOME}/conf/catalina.properties文件,读取要loader的jar包配置
注意,tomcat在catalina.properties 配置文件中指定了:common.loader,catalina.loader,shared.loader但是后2者的配置都为空,网上说是shared.loader 是分享公共的,没有配置的意义。
从上述的initClassLoaders 可以看出使用creatteClassLoader("","") 创建后两者的loader时,都传入了commonLoader, 这样,配置为空,catalinaLoader 其实还是commonLoader.
备注:tomcat使用了org.apache.catalina.startup.CatalinaProperties封装tomcat/conf/catalina.properties文件,其读取配置文件的方式值得学习,代码如下:
private static void loadProperties() {
InputStream is = null;
Throwable error = null;
try {
String configUrl = System.getProperty("catalina.config");
if (configUrl != null) {
is = (new URL(configUrl)).openStream();
}
} catch (Throwable t) {
handleThrowable(t);
}
if (is == null) {
try {
File home = new File(Bootstrap.getCatalinaBase());
File conf = new File(home, "conf");
File propsFile = new File(conf, "catalina.properties");
学习之处:可以看到,第一步是判断有没有catalina.config 指定catalina.conf的配置路径,没有该-D参数才会使用tomcat/conf下的该配置。这个值得学习。
3、反射创建Catalina对象,并设置classLoader
public void init() throws Exception {
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");
**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;
}
3、设置Catalina对象为BootStrap的catalinaDaemon 成员变量
private Object catalinaDaemon = null; //catalinaDaemon 是Catalina对象,该对象的parentClassLoader 属性是sharedClassloader 也就是commonClassLoader
我们可以看到,其中的catalinaDaemon 的声明是Object类型的,降低了tomcat和Catalina的耦合,而且编译Bootstrap时不用提供Catalina的依赖。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。