目录
一、启动脚本
当我们在服务启动Tomcat时,都是通过执行startup.sh脚本启动。在Tomcat的启动脚本startup.sh中,最终会去执行catalina.sh脚本,传递的参数是start。
在catalina.sh脚本中,前面是环境判断和初始化参数,最终根据传递的start来执行上图的代码,最终会调用Tomcat的Bootstrap启动类的main方法,传递的参数是start。
二、源码解析
为了更容易的理解源码,整个系列中Tomcat的运行模式采用BIO的方式。
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];
}
//脚本传递的是start
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")) {
//加载和启动整个Tomcat
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方法中,创建了一个启动类的实例,然后进行初始化,最后再根据启动命令传递进来的参数,也就是上文中的 start 来执行对应的逻辑,即加载和启动整个Tomcat。
public void init() throws Exception {
//设置容器的路径和脚本中的基本信息
setCatalinaHome();
setCatalinaBase();
//初始化Tomcat的三大类加载器
initClassLoaders();
//该类加载器用于加载这个源码的类
Thread.currentThread().setContextClassLoader(catalinaLoader);
SecurityClassLoad.securityClassLoad(catalinaLoader);
//创建一个容器的启动实例,待会用于加载server.xml
Class<?> startupClass =
catalinaLoader.loadClass
("org.apache.catalin