Tomcat -- 启动流程
web概念
- 软件架构
a. C/S:客户端、服务器端架构,如微信,QQ
b. B/S:浏览器、服务器端架构,如淘宝等门户网站 - 资源类别
a. 静态资源:所有用户访问得到的结果都一样,称为静态资源,可以直接被浏览器解析,如html、css、jpg等
b. 动态资源:每个用户访问得到的结果可能不一致,动态资源被访问后需要先转换为静态资源,再返回给浏览器,由浏览器解析,如:jsp、servlet等 - 网络三要素
a. ip:电子设备在网络的唯一标识
b. 端口:应用程序在计算机中的唯一标识
c. 传输协议:规定数据传输的规则
tomcat启动原理
- 加载tomcat配置文件,初始化容器组件,监听对应的端口号,准备接受客户端请求

启动流程
- 启动tomcat,执行bin/startup.bat脚本,调用catalina.bat脚本
- 执行调用BootStrap中main方法,调用init方法,通过反射创建Catalina对象及初始化类加载器
- main方法中调用load方法,会调用Catalina的load方法
- Catalina的load方法会进行Server中的一系列主键的初始化工作,并构造Digester对象,负责解析XML
- 加载tomcat配置文件,初始化容器组件,监听对应的端口号,准备接受客户端请求
启动源码
生命周期方法(Lifecycle)
- 所有组件都存在初始化、启动、停止等生命周期方法,tomcat基于生命周期管理抽象成Lifecycle接口
- 组件Server、Service、Container、Executor、Connector都实现Lifecycle,通过Lifecycle统一管理个组件的生命周期接口
○ init:初始化组件接口
○ start:启动组件接口
○ stop:停止组件接口
○ destroy:销毁组件接口
组件默认实现

源码跟踪

startup.bat 启动文件
:okHome
//调用catalina.bat
set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"
rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find "%EXECUTABLE%"
echo This file is needed to run this program
goto end
:okExec
rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs
//执行
call "%EXECUTABLE%" start %CMD_LINE_ARGS%
:end
catalina.bat (bootstrap.jar)
if "%CLASSPATH%" == "" goto emptyClasspath
set "CLASSPATH=%CLASSPATH%;"
:emptyClasspath
set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar"
启动入口 Bootstrap.main
org.apache.catalina.startup.Bootstrap#main
public static void main(String args[]) {
synchronized (daemonLock) {
//执行init方法初始化,创建Catalina对象
bootstrap.init();
//...
String command = "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")) {
daemon.setAwait(true);
daemon.load(args);
daemon.start();
if (null == daemon.getServer()) {
System.exit(1);
}
} 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);
}
}
}
Bootstrap初始化组件
解析配置xml :org.apache.catalina.startup.Catalina#parseServerXml
初始化Bootstrap – bootstrap.init
- 初始化ClassLoader
- 通过反射创建Catalina(反射解耦)
public void init() throws Exception {
//初始化ClassLoader
initClassLoaders();
Thread.currentThread().setContextClassLoader(catalinaLoader);
SecurityClassLoad.securityClassLoad(catalinaLoader);
//使用自定义ClassLoader类加载器 反射创建Catalina
Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.getConstructor().newInstance();
String methodName = "setParentClassLoader";
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
//反射获取Catalina的setParentClassLoader
Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
//设置父ClassLoader
method.invoke(startupInstance, paramValues);
catalinaDaemon = startupInstance;
}
因为Bootstrap这个类在Tomcat打包发布时是放在bin\bootstrap.jar中,
而Catalina类是放在lib\catalina.jar中,两个jar是用不同的ClassLoader加载的,
所以不能在Bootstrap类中直接引用Catalina类,只能通过反射。
加载Bootstrap – daemon.load(args)
- 执行Bootstrap的load方法
- 反射调用Catalina的load方法
private void load(String[] arguments) throws Exception {
String methodName = "load";
//....
//获取Catalina的load方法
Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes);
//通过反射调用Catalina.load方法
method.invoke(catalinaDaemon, param);
}
加载Catalina – Catalina.load
- 执行初始化
- 解析server.xml配置文件–parseServerXml
– 创建启动或者停止的xml解析器Digester - 创建Server
- 初始化Server
public void load() {
//执行初始化
initDirs();
initNaming();
//解析server.xml配置文件
parseServerXml(true);
//创建Server
Server s = getServer();
//初始化Server
getServer().init();
}
// 解析server.xml
protected void parseServerXml(boolean start) {
//....
try (ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getServerXml()) {
//创建启动或者停止的xml解析器Digester
Digester digester = start ? createStartDigester() : createStopDigester();
//....
} catch (Exception e) {
log.warn(sm.getString("catalina.configFail", file.getAbsolutePath()), e);
if (file.exists() && !file.canRead()) {
log.warn(sm.getString("catalina.incorrectPermissions"));
}
}
}
初始化Server – Lifecycle.init()
- 调用抽象方法,执行具体实现,初始化
- 模板方法模式
- 执行实现的StandardServer.initInternal方法初始化Server
- 循环初始化Service
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
setStateInternal(LifecycleState.INITIALIZING, null, false);
//调用抽象方法,执行具体实现,初始化
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}
protected void initInternal() throws LifecycleException {
super.initInternal();
//初始化
reconfigureUtilityExecutor(getUtilityThreadsInternal(utilityThreads));
register(utilityExecutor, "type=UtilityExecutor");
onameStringCache = register(new StringCache(), "type=StringCache");
// Register the MBeanFactory
MBeanFactory factory = new MBeanFactory();
factory.setContainer(this);
onameMBeanFactory = register(factory, "type=MBeanFactory");
globalNamingResources.init();
//循环初始化Service
for (Service service : services) {
service.init();
}
}
初始化Service – service.init
- 同初始化Server,模板方法调用 Lifecycle.init()
- 调用StandardService.initInternal方法
- 初始化Engine引擎
- 初始化Executor线程连接池
○ tomcat线程池与jdk线程池区别
○ tomcat自定义TaskQueue, 默认队列大小是无限大队列,
○ tomcat重写了offer入队方法,
○ 如果线程池线程数量小于线程池最大线程池,则入队失败(会直接开启非核心线程接收请求,而非入队) - 初始化监听器
- 初始化Connector连接器
protected void initInternal() throws LifecycleException {
super.initInternal();
//初始化Engine引擎
if (engine != null) {
engine.init();
}
//初始化Executor线程池
for (Executor executor : findExecutors()) {
if (executor instanceof JmxEnabled) {
((JmxEnabled) executor).setDomain(getDomain());
}
executor.init();
}
// 初始化监听器
mapperListener.init();
//初始化Connector连接器
synchronized (connectorsLock) {
for (Connector connector : connectors) {
connector.init();
}
}
}
初始化Connector – Connector.initInternal
- 初始化CoyoteAdapter适配器
- 初始化ProtocolHandler
protected void initInternal() throws LifecycleException {
// 初始化CoyoteAdapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
//....
//初始化ProtocolHandler
protocolHandler.init();
}
初始化ProtocolHandler
- 初始化EndPoint
public void init() throws Exception {
//....
String endpointName = getName();
endpoint.setName(endpointName.substring(1, endpointName.length()-1));
endpoint.setDomain(domain);
//初始化EndPoint
endpoint.init();
}
初始化EndPoint – AbstractEndpoint.init
- 绑定Servlet
- 注册EndPoint
public final void init() throws Exception {
if (bindOnInit) {
//绑定Servlet相关能力
bindWithCleanup();
bindState = BindState.BOUND_ON_INIT;
}
if (this.domain != null) {
// 注册EndPoint
oname = new ObjectName(domain + ":type=ThreadPool,name=\"" + getName() + "\"");
Registry.getRegistry(null, null).registerComponent(this, oname, null);
ObjectName socketPropertiesOname = new ObjectName(domain + ":type=SocketProperties,name=\"" + getName() + "\"");
socketProperties.setObjectName(socketPropertiesOname);
Registry.getRegistry(null, null).registerComponent(socketProperties, socketPropertiesOname, null);
for (SSLHostConfig sslHostConfig : findSslHostConfigs()) {
registerJmx(sslHostConfig);
}
}
}
绑定Servlet
- 初始化ServerSocket
- 初始化SSL
public void bind() throws Exception {
//初始化ServerSocket
initServerSocket();
setStopLatch(new CountDownLatch(1));
//初始化SSL
initialiseSsl();
selectorPool.open(getName());
}
//初始化ServerSocket
protected void initServerSocket() throws Exception {
if (!getUseInheritedChannel()) {
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());
serverSock.socket().bind(addr,getAcceptCount());
} else {
Channel ic = System.inheritedChannel();
if (ic instanceof ServerSocketChannel) {
serverSock = (ServerSocketChannel) ic;
}
if (serverSock == null) {
throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited"));
}
}
serverSock.configureBlocking(true); //mimic APR behavior
}
Bootstrap启动
启动Bootstrap – bootstrap.start
- 如果没有初始化,则在此初始化
- 反射调用Catalina的start方法
public void start() throws Exception {
//如果没有初始化,则在此初始化
if (catalinaDaemon == null) {
init();
}
//反射调用Catalina的start方法
Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
method.invoke(catalinaDaemon, (Object [])null);
}
启动Catalina.start
- 启动Server
- 启动失败则销毁Server
public void start() {
//启动Server
try {
getServer().start();
} catch (LifecycleException e) {
try {
//启动失败则销毁
getServer().destroy();
} catch (LifecycleException e1) {
log.debug("destroy() failed for failed Server ", e1);
}
return;
}
if (generateCode) {
// Generate loader which will load all generated classes
generateLoader();
}
// Register shutdown hook
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
false);
}
}
if (await) {
await();
stop();
}
}
启动Server – Lifecycle.start
- 调用抽象方法,执行具体实现,初始化
- 模板方法模式
- 执行实现的StandardServer.startInternal方法启动Server
- 循环启动Service
public final synchronized void start() throws LifecycleException {
//....
setStateInternal(LifecycleState.STARTING_PREP, null, false);
//
startInternal();
}
protected void startInternal() throws LifecycleException {
//循环启动service
synchronized (servicesLock) {
for (Service service : services) {
service.start();
}
}
if (periodicEventDelay > 0) {
monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
new Runnable() {
@Override
public void run() {
startPeriodicLifecycleEvent();
}
}, 0, 60, TimeUnit.SECONDS);
}
}
启动Service – StandardService.startInternal
- 启动Engine引擎
- 启动Executor线程连接池
- 启动监听器
- 启动Connector连接器
protected void startInternal() throws LifecycleException {
// 启动Engine引擎
if (engine != null) {
synchronized (engine) {
engine.start();
}
}
//启动Executor线程连接池
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
//启动监听器
mapperListener.start();
//启动Connector连接器
synchronized (connectorsLock) {
for (Connector connector: connectors) {
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
}
}
}
启动Connector – Connector.startInternal
- 设置状态
- 启动ProtocolHandler
protected void startInternal() throws LifecycleException {
//设置状态
setState(LifecycleState.STARTING);
//启动ProtocolHandler
protocolHandler.start();
}
启动ProtocolHandler – AbstractProtocol.start
public void start() throws Exception {
//启动Endpoint
endpoint.start();
monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
new Runnable() {
@Override
public void run() {
if (!isPaused()) {
startAsyncTimeout();
}
}
}, 0, 60, TimeUnit.SECONDS);
}
启动Endpoint
- 初始化连接
- 启动接收的线程
public final void start() throws Exception {
if (bindState == BindState.UNBOUND) {
bindWithCleanup();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
public void startInternal() throws Exception {
//初始化连接
initializeConnectionLatch();
//启动接收的线程
startAcceptorThread();
}
Acceptor接收器 – socket.accept
- 实现Runnable
- run方法接收客户端请求
- socket.accept监听接收客户端请求
public class Acceptor<U> implements Runnable {
@Override
public void run() {
//接收客户端请求
socket = endpoint.serverSocketAccept();
}
}
//socket.accept监听接收客户端请求
protected SocketChannel serverSocketAccept() throws Exception {
return serverSock.accept();
}
参考资源: Java进阶教程Tomcat核心原理解析