Bootstrap主入口?
Tomcat源码就从它的main方法开始。Tomcat的main方法在org.apache.catalina.startup.Bootstrap 里。 如下代码我们就是创建一个 Bootstrap 对象,调用它的 init 方法初始化,然后根据启动参数,分别调用 Bootstrap 对象的不同方法。
php
/**
* 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) {
// 创建一个Bootstrap对象,调用它的init方法初始化
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);
log.error("Init exception", t);
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);
}
}
// 根据启动参数,分别调用BootStrap对象的不同方法
try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
switch (command) {
case "startd":
args[args.length - 1] = "start";
daemon.load(args);
daemon.start();
break;
case "stopd":
args[args.length - 1] = "stop";
daemon.stop();
break;
case "start":
daemon.setAwait(true);
daemon.load(args);
daemon.start();
if (null == daemon.getServer()) {
System.exit(1);
}
break;
case "stop":
daemon.stopServer(args);
break;
case "configtest":
daemon.load(args);
if (null == daemon.getServer()) {
System.exit(1);
}
System.exit(0);
break;
default:
log.warn("Bootstrap: command "" + command + "" does not exist.");
break;
}
} catch (Throwable t) {
// Unwrap the Exception for clearer error reporting
Throwable throwable = t;
if (throwable instanceof InvocationTargetException && throwable.getCause() != null) {
throwable = throwable.getCause();
}
handleThrowable(throwable);
log.error("Error running command", throwable);
System.exit(1);
}
}
Catalina是如何初始化的
ini
/**
* Initialize daemon.
* 初始化守护进程
*
* @throws Exception Fatal initialization error
*/
public void init() throws Exception {
// 初始化classloader(包括catalinaLoader)
initClassLoaders();
// 设置当前的线程的contextClassLoader为catalinaLoader
Thread.currentThread().setContextClassLoader(catalinaLoader);
// 通过catalinaLoader加载Catalina,并初始化startupInstance 对象
// Load our startup class and call its process() method
if (log.isTraceEnabled()) {
log.trace("Loading startup class");
}
Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.getConstructor().newInstance();
// 通过反射调用了setParentClassLoader 方法
// Set the shared extensions class loader
if (log.isTraceEnabled()) {
log.trace("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;
}