在上文揭开tomcat神秘的面纱之bootstrap初始化中,本菜鸟分析了bootstrap最终会经过初始化,加载,启动三个步骤。接着来分析加载过程。
加载过程如下:
在加载过程中,实质是利用反射,调用catalina
的load()
方法.
//bootstrap.java
private void load(String[] arguments)
throws Exception {
String methodName = "load";
//利用反射调用catalina的load方法 此处的catalinaDaemon为catalina
Method method =
catalinaDaemon.getClass().getMethod(methodName, paramTypes);
method.invoke(catalinaDaemon, param);
}
在catalina加载过程中,会解析加载conf/server.xml
文件,初始化server
。
//catalina.java
public void load() {
initDirs();
initNaming();
Digester digester = createStartDigester();//创建解析器,degister解析xml文件使用
InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
file = configFile();//文件为conf/server.xml
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
if (inputStream == null) {
inputStream = getClass().getClassLoader()
.getResourceAsStream(getConfigFile());
inputSource = new InputSource
(getClass().getClassLoader()
.getResource(getConfigFile()).toString());
}
if (inputStream == null) {
inputStream = getClass().getClassLoader()
.getResourceAsStream("server-embed.xml");
inputSource = new InputSource
(getClass().getClassLoader()
.getResource("server-embed.xml").toString());
}
if (inputStream == null || inputSource == null) {
return;
}
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);//server初始化在这里
getServer().setCatalina(this);//设置server的catalina
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
initStreams();
getServer().init();//初始化server
}
而在server中初始化过程中,实则是调用调用StandardService
的init();
方法。
//StandardServer.java
//LifecycleBase.java
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
setStateInternal(LifecycleState.INITIALIZING, null, false);//INITIALIZING事件
initInternal();//在这里初始化
setStateInternal(LifecycleState.INITIALIZED, null, false);//初始化成功事件
}
protected void initInternal() throws LifecycleException {
super.initInternal();
onameStringCache = register(new StringCache(), "type=StringCache");
MBeanFactory factory = new MBeanFactory();
factory.setContainer(this);
onameMBeanFactory = register(factory, "type=MBeanFactory");
globalNamingResources.init();
if (getCatalina() != null) {//加载jar包资源
ClassLoader cl = getCatalina().getParentClassLoader();
while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
if (cl instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url : urls) {
if (url.getProtocol().equals("file")) {
File f = new File (url.toURI());
if (f.isFile() &&
f.getName().endsWith(".jar")) {
ExtensionValidator.addSystemResource(f);
}
}
}
}
cl = cl.getParent();
}
}
for (int i = 0; i < services.length; i++) {
services[i].init();//调用StandardService 的init方法。
}
}
而在StandardService
的init();
方法中,实质调用和server
一样,都会调用initInternal()
方法,两者都继承与LifecycleBase
接口,而在StandardService
中,则是初始化了engine
和connector
,这两个配置都是在conf/server.xml
中。
@Override
//StandardService.java
protected void initInternal() throws LifecycleException {
super.initInternal();
if (engine != null) {
engine.init();//初始化engine在这里
}
for (Executor executor : findExecutors()) {
if (executor instanceof JmxEnabled) {
((JmxEnabled) executor).setDomain(getDomain());
}
executor.init();
}
mapperListener.init();
synchronized (connectorsLock) {
for (Connector connector : connectors) {
connector.init();//初始化连接器
}
}
}
而在初始化connection
的时候,实际是调用protocolHandler(AjpNio2Protocol)
的init();
方法,初始化 endPoint
protected void initInternal() throws LifecycleException {
super.initInternal();
if (protocolHandler == null) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"));
}
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
if (null == parseBodyMethodsSet) {
setParseBodyMethods(getParseBodyMethods());
}
if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) {
throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoApr",
getProtocolHandlerClassName()));
}
if (AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseOpenSSL() &&
protocolHandler instanceof AbstractHttp11JsseProtocol) {
AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
(AbstractHttp11JsseProtocol<?>) protocolHandler;
if (jsseProtocolHandler.isSSLEnabled() &&
jsseProtocolHandler.getSslImplementationName() == null) {
// OpenSSL is compatible with the JSSE configuration, so use it if APR is available
jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
}
}
protocolHandler.init();//实例AjpNio2Protocol,在这里初始化endPoint.
}
public void init() throws Exception {
if (oname == null) {
oname = createObjectName();
if (oname != null) {
Registry.getRegistry(null, null).registerComponent(this, oname, null);
}
}
if (this.domain != null) {
rgOname = new ObjectName(domain + ":type=GlobalRequestProcessor,name=" + getName());
Registry.getRegistry(null, null).registerComponent(
getHandler().getGlobal(), rgOname, null);
}
String endpointName = getName();
endpoint.setName(endpointName.substring(1, endpointName.length()-1));
endpoint.setDomain(domain);
endpoint.init();//初始化endPoint
}
而在endPoint
初始化过程中,实则是打开了ServerSocketChannel
,调用了Selector
的open()
方法。
//EndPoint.java
public final void init() throws Exception {
if (bindOnInit) {
bind();//在这里初始化ServerSocket
bindState = BindState.BOUND_ON_INIT;
}
if (this.domain != null) {
oname = new ObjectName(domain + ":type=ThreadPool,name=\"" + getName() + "\"");
Registry.getRegistry(null, null).registerComponent(this, oname, null);
for (SSLHostConfig sslHostConfig : findSslHostConfigs()) {
registerJmx(sslHostConfig);
}
}
}
@Override
public void bind() throws Exception {
initServerSocket();//初始化ServerSocket
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
if (pollerThreadCount <= 0) {
pollerThreadCount = 1;
}
setStopLatch(new CountDownLatch(pollerThreadCount));
initialiseSsl();
selectorPool.open();//selector.open();
}
protected void initServerSocket() throws Exception {
if (!getUseInheritedChannel()) {
serverSock = ServerSocketChannel.open();//初始化ServerSocket
socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
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); //设置非阻塞
}