从Tomcat启动开始的源码分析
Tomcat启动分析
承接上文Bootstrap类启动都是通过Java反射机制调用Catalina类的方法。
1. org.apache.catalina.startup.Catalina.class
(1) start方法的流程图
主要是获取server对象,如果获取不到server对象,就调用load方法去加载server对象.
然后调用server对象的start方法,完成启动.
(2) load方法的流程图
主要是加载配置文件"conf/server.xml", 通过创建digester对象解析配置文件.
在解析配置文件之前,会先调用digester对象的push方法,传入当前的Catalina对象作为参数.
解析成功之后,server变量引用一个Server对象,默认是org.apache.catalina.core.StandardServer类型的对象,然后调用server对象的setCatalina,setCatalinaHome,setCatalinaBase和init方法,进行对象初始化.
(3) start方法中为什么要使用shutdownHook?
start方法利用shutdown hook,确保用户突然退出应用程序时会执行server对象的stop方法.
Java 关闭钩子的介绍参考如下博客链接: JDK ShutdownHook - 优雅地停止服务
// Register shutdown hook
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
// If JULI is being used, disable JULI's shutdown hook since
// shutdown hooks run in parallel and log messages may be lost
// if JULI's hook completes before the CatalinaShutdownHook()
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
false);
}
}
if (await) {
await();
stop();
}
(4) await方法
Catalina对象的start方法会调用server对象的await方法,server对象会使用一个专用的线程来等待关闭命令.await方法会循环等待,直到接收到正确的关闭命令.
(5) stop方法
当await方法返回时,Catalina对象的start方法会调用server对象的stop和destroy方法,从而关闭server对象和其他的组件.
如果使用了关闭钩子,则会在stop方法中移除原先注册的shutdownHook.
/**
* Stop an existing server instance.
*/
public void stop() {
try {
// Remove the ShutdownHook first so that server.stop()
// doesn't get invoked twice
if (useShutdownHook) {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
// If JULI is being used, re-enable JULI's shutdown to ensure
// log messages are not lost
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
true);
}
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// This will fail on JDK 1.2. Ignoring, as Tomcat can run
// fine without the shutdown hook.
}
// Shut down the server
try {
Server s = getServer();
LifecycleState state = s.getState();
if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
&& LifecycleState.DESTROYED.compareTo(state) >= 0) {
// Nothing to do. stop() was already called
} else {
s.stop();
s.destroy();
}
} catch (LifecycleException e) {
log.error(sm.getString("catalina.stopError"), e);
}
}