Tomcatのソースを読んでみる - Catalinaの読み込み
Web開発のアプリケーションサーバとして日頃とてもお世話になっているTomcat。
今まで使用させて頂いているだけで、その中身のソースについてはほぼ無勉強でした。
Javaで書かれているので、普段Javaを書いている私にも解読しやすいのでは?と思い、この機会にTomcatのソースリーディングしてみます。
まず、Tomcatの概要から調べてみます。
Tomcatの特徴
・開発元はApacheSoftwareFoundation。
・トップレベルプロジェクトのApacheTomcatProjectである。
・以前はApacheJakartaProjectだった。
・Javaプラットフォームで動作する。
・Webコンテナ(コンテナとはアプリケーション実行環境)と呼ばれる。
・ServletコンテナとしてServlet/JSPの動的コンテンツの仕組みを提供する。
・Servletコンテナがリクエスト毎にスレッド起動する。CGIより負荷が小さい。
・セッション管理ができる。
Tomcatの構成
・Catalina - Servlet コンテナ
・Coyote - HTTPサーバー
・Jasper, Jasper2 - JSP
Tomcatのディレクトリ構造
・bin - 実行ファイル類
・conf - 設定ファイル類
・lib
・temp
・logs - ログファイル類
・webapp - アプリケーションファイル
・work
Tomcatの主なクラス
・Bootstrapクラス
・Catalinaクラス
・Digesterクラス
・StandardEngineクラス
・StandardServerクラス
・StandardServiceクラス
では、実際にTomcatのソースを見て、Tomcatの処理を確認してみます。
まずは有名なBootstrapクラスから見てみます。
*分かりやすいようにメソッドの順番を変更しています。
public final class Bootstrap { /** * Daemon object used by main. */ private static Bootstrap daemon = null; // -------------------------------------------------------------- Variables /** * Daemon reference. */ private Object catalinaDaemon = null; protected ClassLoader commonLoader = null; protected ClassLoader catalinaLoader = null; protected ClassLoader sharedLoader = null; public static void main(String args[]) { if (daemon == null) { daemon = new Bootstrap(); try { daemon.init(); } catch (Throwable t) { t.printStackTrace(); return; } } try { 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 { log.warn("Bootstrap: command \"" + command + "\" does not exist."); } } catch (Throwable t) { t.printStackTrace(); } } /** * Initialize daemon. */ public void init() throws Exception { // Set Catalina path setCatalinaHome(); setCatalinaBase(); initClassLoaders(); Thread.currentThread().setContextClassLoader(catalinaLoader); SecurityClassLoad.securityClassLoad(catalinaLoader); // Load our startup class and call its process() method if (log.isDebugEnabled()) log.debug("Loading startup class"); Class startupClass = catalinaLoader.loadClass ("org.apache.catalina.startup.Catalina"); Object startupInstance = startupClass.newInstance(); // Set the shared extensions class loader if (log.isDebugEnabled()) log.debug("Setting startup class properties"); String methodName = "setParentClassLoader"; Class paramTypes[] = new Class[1]; paramTypes[0] = Class.forName("java.lang.ClassLoader"); Object paramValues[] = new Object[1]; paramValues[0] = sharedLoader; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); catalinaDaemon = startupInstance; } private void initClassLoaders() { try { commonLoader = createClassLoader("common", null); if( commonLoader == null ) { // no config file, default to this loader - we might be in a 'single' env. commonLoader=this.getClass().getClassLoader(); } catalinaLoader = createClassLoader("server", commonLoader); sharedLoader = createClassLoader("shared", commonLoader); } catch (Throwable t) { log.error("Class loader creation threw exception", t); System.exit(1); } }
Bootstrap#mainで自身のインスタンスを作成し、
daemonにセットした後、daemon.init()で初期化処理を行います。
初期化処理では、initClassLoaders()でCatalinaPropertiesクラスを使って、
commonLoader、catalinaLoader、sharedLoaderを初期化しています。
そして、Catalinaクラスのインスタンスを生成し、
setParentClassLoaderを呼び出し、catalinaDaemonにセットしています。
/** * Load daemon. */ private void load(String[] arguments) throws Exception { // Call the load() method String methodName = "load"; Object param[]; Class paramTypes[]; if (arguments==null || arguments.length==0) { paramTypes = null; param = null; } else { paramTypes = new Class[1]; paramTypes[0] = arguments.getClass(); param = new Object[1]; param[0] = arguments; } Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes); if (log.isDebugEnabled()) log.debug("Calling startup class " + method); method.invoke(catalinaDaemon, param); }
daemon.load()でCatalina#loadを呼び出しています。
public class Catalina extends Embedded { protected String configFile = "conf/server.xml"; /* * Load using arguments */ public void load(String args[]) { try { if (arguments(args)) load(); } catch (Exception e) { e.printStackTrace(System.out); } } /** * Start a new server instance. */ public void load() { long t1 = System.nanoTime(); initDirs(); // Before digester - it may be needed initNaming(); // Create and execute our Digester Digester digester = createStartDigester(); //--------------------------------------------------------中略 }
Catalina#load()では、createStartDigester()にて、オブジェクトやルール
を設定してDigesterオブジェクトを作成しています。
そして、次からはconf/server.xmlを読み込んでいくのですが、
ちょっと長くなったので、次回に続きます。
WEBアプリケーション・サーバー 設計・構築ノウハウ 第2版
- 作者: NTTデータ先端技術株式会社 NTTデータ株式会社著,日経SYSTEMS
- 出版社/メーカー: 日経BP社
- 発売日: 2010/04/15
- メディア: 単行本
- 購入: 6人 クリック: 336回
- この商品を含むブログ (6件) を見る