前言
上一篇文章中我们讨论了Bootstrap
类中main
方法中涉及到的load
方法,今天这篇文章我们来查看下start
方法。
/**
* Start the Catalina daemon.
*/
public void start()
throws Exception {
if( catalinaDaemon==null ) init();
Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
method.invoke(catalinaDaemon, (Object [])null);
}
具体代码就不分析了,可以看出start
方法使用了反射调用了catalinaDaemon
的start
方法,而catalinaDeamon
是类Catalina
的实例,直接查看Catalina
类的start
方法
Catalina类
/**
* Start a new server instance.
*/
public void start() {
//...判断代码
// Start the new server
try {
//11111
getServer().start();
} catch (LifecycleException e) {
log.fatal(sm.getString("catalina.serverStartFail"), e);
try {
getServer().destroy();
} catch (LifecycleException e1) {
log.debug("destroy() failed for failed Server ", e1);
}
return;
}
long t2 = System.nanoTime();
if(log.isInfoEnabled()) {
log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
}
//22222222
// 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);
}
}
//333333333333
if (await) {
await();
stop();
}
}
可以看出来除了一些判断意外,start
方法基本分成了3个步骤,我们依次来查看。
第一步
在第一步调用了getServer().start()
方法,其实也就是调用了StandardServer
的start
方法,我们查看StandardServer
类发现,他并没有start
方法,继续查看其父类,发现其父类包含了LifecycleBase
,其中实现了start
方法,而在start
方法中又调用了startInternal
方法,所以看到这里大概也明白了,start
这个方法类似init
方法,也使用了模版设计模式,所以我们直接看StandardServer
类的startInternal
方法就可以了。
@Override
protected void startInternal() throws LifecycleException {
fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING);
globalNamingResources.start();
// Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
除了调用了globalNamingResources
的start
方法,还调用了本身Service
的start
方法,由于globalNamingResources
是一个组件,我们这里暂时不介绍,有兴趣可以自己跟源码查看,我们来看下service
的start
方法, 也就是StandardService
的startInternal
方法。
@Override
protected void startInternal() throws LifecycleException {
if(log.isInfoEnabled())
log.info(sm.getString("standardService.start.name", this.name));
setState(LifecycleState.STARTING);
// Start our defined Container first
if (container != null) {
//11111
synchronized (container) {
container.start();
}
}
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
// Start our defined Connectors second
synchronized (connectorsLock) {
for (Connector connector: connectors) {
try {
//222222
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
}
}
可以看到StandardService
的startInternal
方法主要做了2个动作,第一个是调用了Container
的start
方法,第二个是调用了Connector
的start
方法,我们先看Container
的start
方法,也就是对应实现类StandardEngine
的startInternal
方法。
@Override
protected synchronized void startInternal() throws LifecycleException {
// Log our server identification information
if(log.isInfoEnabled())
log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());
// Standard container startup
super.startInternal();
}
查看类继承关系
public class StandardEngine extends ContainerBase implements Engine
查看类ContainerBase
中的startInternal
方法
@Override
protected synchronized void startInternal() throws LifecycleException {
//启动各种组件
// Start our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
logger = null;
getLogger();
if ((manager != null) && (manager instanceof Lifecycle))
((Lifecycle) manager).start();
if ((cluster != null) && (cluster instanceof Lifecycle))
((Lifecycle) cluster).start();
Realm realm = getRealmInternal();
if ((realm != null) && (realm instanceof Lifecycle))
((Lifecycle) realm).start();
if ((resources != null) && (resources instanceof Lifecycle))
((Lifecycle) resources).start();
//获取子容器,启动所有的子容器
//子容器主要是 Host 对应实现类 StandardHost 调用其startInternal方法
// Start our child containers, if any
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<Future<Void>>();
for (int i = 0; i < children.length; i++) {
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
boolean fail = false;
for (Future<Void> result : results) {
try {
result.get();
} catch (Exception e) {
log.error(sm.getString("containerBase.threadedStartFailed"), e);
fail = true;
}
}
if (fail) {
throw new LifecycleException(
sm.getString("containerBase.threadedStartFailed"));
}
//启动pipeline 组件
// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
setState(LifecycleState.STARTING);
//启动container 后台线程
// Start our thread
threadStart();
}
从代码的注释中可以清楚的看到StandardEngine
的startInternal
方法都做了什么,我们继续查看Connector
的startInternal
方法。
@Override
protected void startInternal() throws LifecycleException {
// Validate settings before starting
if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}
setState(LifecycleState.STARTING);
try {
//11
protocolHandler.start();
} catch (Exception e) {
String errPrefix = "";
if(this.service != null) {
errPrefix += "service.getName(): "" + this.service.getName() + ""; ";
}
throw new LifecycleException
(errPrefix + " " + sm.getString
("coyoteConnector.protocolHandlerStartFailed"), e);
}
//2
mapperListener.start();
}
我们可以看到Connector
的startInternal
方法主要做了两件事,第一件是调用了变量protocolHandler
的start
方法,第二件事是调用了mapperListener
的start
方法,我们主要看下protocolHandler
的调用。
类似init
方法讲解中提到的,protocolHandler
有两个实例分别代表http
请求和ajb
请求,我们主要看对应http
请求,也就是实例Http11Protocol
的startInternal
方法。我们查看类Http11Protocol
发现其中并无start
方法相关,查看其父类AbstractProtocol
发现其中的start
方法。
@Override
public void start() throws Exception {
if (getLog().isInfoEnabled())
getLog().info(sm.getString("abstractProtocolHandler.start",
getName()));
try {
endpoint.start();
} catch (Exception ex) {
getLog().error(sm.getString("abstractProtocolHandler.startError",
getName()), ex);
throw ex;
}
}
其中调用了endpoint
的start
方法。而在Http11Protocol
类的构造方法中可以看到
public Http11Protocol() {
endpoint = new JIoEndpoint();
cHandler = new Http11ConnectionHandler(this);
((JIoEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}
endpoint
是类JIoEndpoint
的实例,我们继续查看JIoEndpoint
@Override
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
// Create worker collection
if (getExecutor() == null) {
createExecutor();
}
initializeConnectionLatch();
startAcceptorThreads();
// Start async timeout thread
Thread timeoutThread = new Thread(new AsyncTimeout(),
getName() + "-AsyncTimeout");
timeoutThread.setPriority(threadPriority);
timeoutThread.setDaemon(true);
timeoutThread.start();
}
}
看到这里Connector
的start
方法就结束了,StandardService
的start
方法也结束了。
在文章的最开始我们提到了Catalina
类的start
方法,上面跟源码分析了那么多其实一直是分析getServer().start()
,下一篇文章我们继续分析Catalina
类的start
方法的剩余部分。