通过startup.sh启动Tomcat后会发生什么呢?
Tomcat也是Java程序,因此startup.sh脚本会启动一个JVM运行Tomcat的启动类Bootstrap
Bootstrap主要负责初始化Tomcat的类加载器,并创建Catalina
Catalina是个启动类,解析server.xml、创建相应组件,并调用Server#start
Server组件负责管理Service组件,会调用Service#start
Service组件负责管理连接器和顶层容器Engine,因此会调用连接器和Engine的start()
这些启动类或组件不处理具体的请求,它们主要是“管理”,管理下层组件的生命周期,并给下层组件分配任务,即路由请求到应负责的组件。
Catalina
主要负责创建Server,并非直接new个Server实例就完事了,而是:
- 解析server.xml,将里面配的各种组件创建出来
- 接着调用Server组件的init、start方法,这样整个Tomcat就启动起来了
Catalina还需要处理各种“异常”,比如当通过“Ctrl + C”关闭Tomcat时,
Tomcat会如何优雅停止并清理资源呢?
因此Catalina在JVM中注册一个 关闭钩子。
public void start() { // 1. 如果持有的Server实例为空,就解析server.xml创建出来 if (getServer() == null) { load(); } // 2. 如果创建失败,报错退出 if (getServer() == null) { log.fatal(sm.getString("catalina.noServer")); return; } // 3.启动Server try { getServer().start(); } catch (LifecycleException e) { return; } // 创建并注册关闭钩子 if (useShutdownHook) { if (shutdownHook == null) { shutdownHook = new CatalinaShutdownHook(); } Runtime.getRuntime().addShutdownHook(shutdownHook); } // 监听停止请求 if (await) { await(); stop(); } }
关闭钩子
若需在JVM关闭时做一些清理,比如:
- 将缓存数据刷盘
- 清理一些临时文件
就可以向JVM注册一个关闭钩子,其实就是个线程,JVM在停止之前会尝试执行该线程的run()。
Tomcat的关闭钩子 就是CatalinaShutdownHook:
Tomcat的“关闭钩子”实际上就执行了Server#stop,会释放和清理所有资源。