tomcatソース学習2----起動プロセス
今回はtomcatの起動プロセスを分析します.
一、main関数分析
tomcatのエントリ関数は:org.apache.catalina.startup.mainのこの関数で最も重要なコードセグメントは次のとおりです.
ここから、起動パラメータが「start」の場合、実際に呼び出されるのはBootstrapであることがわかる.start()関数(daemonはBootstrapクラスのインスタンスです)、次にstart()関数を解析します.
二、start関数分析
Bootstrap.start()関数のコード:
本質的にcatalinaDaemonのstart関数が呼び出されていることがわかりますが、catalinaDaemonはどのクラスのインスタンスですか?次のコードを使用して、次のことを確認します.
コードはorgに進みますapache.catalina.startup.Catalina.start()で行き、
ここで最も重要な2つの関数は、1、load()、プロファイルのロード2、getServe日()です.start()は、サービスの開始です.もう1つ注意しなければならないのはawait()関数です.この関数は実際にはshutdownコマンドを監視しています.デフォルトは8005ポートで、プロファイルで設定できます.
三、配置ファイルのロード
tomcatのプロファイルのロードはorg.apache.catalina.startup.Catalina.load()関数で完了したコードは次のとおりです.
この関数では主に3つのことをしました:1、xml解析実行構成を構築しました2、構成ファイルを解析し、最初のステップで生成した構築方式に基づいてtomcatのすべてのインスタンスを構築しました.3、サービスインスタンスが第2ステップで構築されたサービスを初期化する.初期化された論理プロシージャは、起動プロシージャの論理と非常に類似しており、特定の論理は起動プロシージャを参照することができる.具体的なロードプロセスは、次のブログで分析されます.
四、サービスの起動過程
start関数でgetServer()が呼び出されます.start()関数はtomcatサービスを起動することです.解析によりgetServer関数がorgを返すことがわかる.apache.catalina.core.StandardServerクラスのインスタンス.start関数はそのベースクラスorgである.apache.catalina.util.LifecycleBaseで実装されているキーコードは次のとおりです.
この関数の本質はstartInternal関数を呼び出し、StandardServerクラスでこの関数を実現することであり、そのキーコードは以下の通りである.
serverの起動中に実際に呼び出されたのは、各servicesのstart関数であることがわかります.ここでのservicesのデフォルトはStandardServiceのインスタンスであり、StandardServiceもLifecycleBaseを継承しているので、本質的にはStandardServiceのstartInternal関数が呼び出されます.この関数のキーコードは、
この関数では主に3つのことをしました:1、containerを呼び出すstart関数、containerのデフォルトはorg.apache.catalina.core.StandardEngineのインスタンスで、LifecycleBaseも継承されています.2、すべてのExecutorのstart関数を呼び出し、ExecutorもLifecycleBaseを継承します.3、すべてのconnectorのstart関数を呼び出し、connectorはorg.apache.catalina.connector.Connectorのインスタンスで、LifecycleBaseも継承されています.
containerのstartコードは本質的に実行されるContainerBaseである.startInternal関数、キーコード:
ここでもLifecycleBaseインスタンスのstart関数を呼び出して起動します.
コネクタのstart呼び出しのキーコード:
ここで最も重要なのはhttpのhandlerのstartを呼び出し、イーサネットサーバを起動し、データの受信を待つことであり、具体的な起動と実行原理は後で分析される.
これでtomcatの起動過程はすでに初歩的に分析して遊んだ.
一、main関数分析
tomcatのエントリ関数は:org.apache.catalina.startup.mainのこの関数で最も重要なコードセグメントは次のとおりです.
public static void main(String args[]) {
//......
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
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();
} 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);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
//......
}
ここから、起動パラメータが「start」の場合、実際に呼び出されるのはBootstrapであることがわかる.start()関数(daemonはBootstrapクラスのインスタンスです)、次にstart()関数を解析します.
二、start関数分析
Bootstrap.start()関数のコード:
public void start()
throws Exception {
if( catalinaDaemon==null ) init();
Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
method.invoke(catalinaDaemon, (Object [])null);
}
本質的にcatalinaDaemonのstart関数が呼び出されていることがわかりますが、catalinaDaemonはどのクラスのインスタンスですか?次のコードを使用して、次のことを確認します.
public void init()throws Exception
{
// ......
Class<?> startupClass =
catalinaLoader.loadClass
("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();
//......
catalinaDaemon = startupInstance;
}
コードはorgに進みますapache.catalina.startup.Catalina.start()で行き、
public void start() {
if (getServer() == null) {
load();
}
//......
getServer().start();
//......
if (await) {
await();
stop();
}
}
ここで最も重要な2つの関数は、1、load()、プロファイルのロード2、getServe日()です.start()は、サービスの開始です.もう1つ注意しなければならないのはawait()関数です.この関数は実際にはshutdownコマンドを監視しています.デフォルトは8005ポートで、プロファイルで設定できます.
三、配置ファイルのロード
tomcatのプロファイルのロードはorg.apache.catalina.startup.Catalina.load()関数で完了したコードは次のとおりです.
public void load() {
//......
Digester digester = createStartDigester();
//......
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);
//......
getServer().init();
//......
}
この関数では主に3つのことをしました:1、xml解析実行構成を構築しました2、構成ファイルを解析し、最初のステップで生成した構築方式に基づいてtomcatのすべてのインスタンスを構築しました.3、サービスインスタンスが第2ステップで構築されたサービスを初期化する.初期化された論理プロシージャは、起動プロシージャの論理と非常に類似しており、特定の論理は起動プロシージャを参照することができる.具体的なロードプロセスは、次のブログで分析されます.
四、サービスの起動過程
start関数でgetServer()が呼び出されます.start()関数はtomcatサービスを起動することです.解析によりgetServer関数がorgを返すことがわかる.apache.catalina.core.StandardServerクラスのインスタンス.start関数はそのベースクラスorgである.apache.catalina.util.LifecycleBaseで実装されているキーコードは次のとおりです.
@Override
public final synchronized void start() throws LifecycleException {
//......
startInternal();
//......
}
この関数の本質はstartInternal関数を呼び出し、StandardServerクラスでこの関数を実現することであり、そのキーコードは以下の通りである.
@Override
protected void startInternal() throws LifecycleException {
// ......
synchronized (services) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
serverの起動中に実際に呼び出されたのは、各servicesのstart関数であることがわかります.ここでのservicesのデフォルトはStandardServiceのインスタンスであり、StandardServiceもLifecycleBaseを継承しているので、本質的にはStandardServiceのstartInternal関数が呼び出されます.この関数のキーコードは、
@Override
protected void startInternal() throws LifecycleException {
//......
if (container != null) {
synchronized (container) {
container.start();
}
}
//......
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
//......
synchronized (connectors) {
for (Connector connector: connectors) {
try {
// 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);
}
}
}
}
この関数では主に3つのことをしました:1、containerを呼び出すstart関数、containerのデフォルトはorg.apache.catalina.core.StandardEngineのインスタンスで、LifecycleBaseも継承されています.2、すべてのExecutorのstart関数を呼び出し、ExecutorもLifecycleBaseを継承します.3、すべてのconnectorのstart関数を呼び出し、connectorはorg.apache.catalina.connector.Connectorのインスタンスで、LifecycleBaseも継承されています.
containerのstartコードは本質的に実行されるContainerBaseである.startInternal関数、キーコード:
@Override
protected synchronized void startInternal() throws LifecycleException {
// ......
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();
// 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 (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
setState(LifecycleState.STARTING);
// Start our thread
threadStart();
}
ここでもLifecycleBaseインスタンスのstart関数を呼び出して起動します.
コネクタのstart呼び出しのキーコード:
@Override
protected void startInternal() throws LifecycleException {
//......
protocolHandler.start();
//......
}
ここで最も重要なのはhttpのhandlerのstartを呼び出し、イーサネットサーバを起動し、データの受信を待つことであり、具体的な起動と実行原理は後で分析される.
これでtomcatの起動過程はすでに初歩的に分析して遊んだ.