前言
上一篇文章分析到,Tomcat通过startup.bat文件启动的时候,传递了一系列参数,最终又调用了Bootstrap.java
的main
方法,现在我们就来看看Bootstrap.java
的main
方法都做了什么吧!
public static void main(String args[]) {
//第一部分
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();
} 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);
}
}
看源码我们大概看到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;
} 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);
}
- 如果成员变量
demon
为空,新建Bootstrap对象,调用对象的init
方法,然后该对象赋给成员变量demon
。 - 如果demon非空,那么当当前线程的类加载器设置为
demon
的加载器,(这个demon.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();
} 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);
}
- 设置command参数为start,如果args存在参数的话,取最后一个(我们这里是启动tomcat所以是
start
)。 - 直接跳转到
start
的if判断,这里做了三个动作,第一个动作设置deamon的await
属性为true
,嗲用deamon变量的load
方法,调用deamon变量的start
方法。
Bootstrap的main方法总结:
如果基于启动的话,main方法主要做了4件事情:
- new(BootStrap)对象,赋值给成员变量
deamon
,并且调用了deamon
类的init
方法。 - 设置
deamon
类的await
属性为true
。 - 调用
deamon
类的load
方法。 - 调用
deamon
类的start
方法。
由此可见Tomcat所有的启动过程就几种在init
,load
,start
三个方法中了,下文我们继续探寻三个方法分别做了什么!