ソースはTomcatの初期化と起動プロセスを追跡Tomcat04--

1.ソース入口

catalina.bat binディレクトリで、次のコードは、MAINCLASS = org.apache.catalina.startup.Bootstrapに設定されているクラスが開始されTOMCAT、メインクラスの位置を示しています。

場所のスタート:ORG / apacheの/カタリナ/起動/ Bootstrap.java

2.初期化プロセス

2.1メインクラスの初期化

2.1.1初期化するために、init()メソッドを呼び出します

if (daemon == null) {
    // Don't set daemon until init() has completed
    Bootstrap bootstrap = new Bootstrap();
    try {
          bootstrap.init();
    } catch (Throwable t) {
           handleThrowable(t);
           t.printStackTrace();
           return;
     }
     daemon = bootstrap;
} 

2.1.2グループクラスのinit()メソッド

主な役割は、initターゲットカタリナを作成することです

メインコードの中国のコメント欄を見てください

 public void init() throws Exception {
        // 初始化类加载器
        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");

        // 通过反射创建Catalina对象
        Object startupInstance = startupClass.getConstructor().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);

        // 将Catalina对象startupInstance赋值给catalinaDaemon
        catalinaDaemon = startupInstance;
    }

2.1.3メインクラスのロードは、初期化メソッドの後に実行されます

マスタークラスの初期化の後、我々はいくつかのコマンドパラメータ文を実行し始めます

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();
                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);
            } else {
                log.warn("Bootstrap: command \"" + command + "\" does not exist.");
            }
        } 

コマンドパラメータは、例えば、起動に対応する負荷方法を、見つけます:

 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);
        }
        // 调用catalina的load方法
        method.invoke(catalinaDaemon, param);
    }

2.2カタリナ

次に行う負荷方法カタリナ

public void load(String args[]) {

        try {
            if (arguments(args)) {
                // 调用load的重载方法,执行逻辑
                load();
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }

その後、負荷に上院負荷引数なしのメソッド呼び出しがあります

getServer().init();

TomcatののXML解析ツールの作成2.2.1

// Digester是tomcat的xml文件解析根据,解析server.xml
Digester digester = createStartDigester();

2.2.2サーバオブジェクトのget

実行中の一連の処置後、

getServer().init();

Serverオブジェクトを取得した後、()メソッドServerオブジェクトのinitを呼び出します

2.3サーバー

ライフサイクルのコンポーネントのTomcat、そこライフサイクル・インターフェースでは、クラスLifeCycleBase、単にgetServer()INITを達成した();.初期化は、実際のinitメソッドLifeCycleBaseで呼び出されます。

 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());
        }
    }

INITで発見された順番にinitInternalメソッドを呼び出します。このメソッドの最後の呼び出しは、initInternalのサーバーStandardServerと呼ばれる実装クラスですinitInternalクラスの実装にあるのでinitInternalは、LifeCycleBase抽象メソッドです。

彼らはサービスのinitメソッドを呼び出しinitInternal方法を、入力します

// 一个Server下可以有多个service
for (int i = 0; i < services.length; i++) {
   services[i].init();
}

2.4サービス

前の手順のように、initInternalのStandardService、それぞれ初期化エンジン(エンジン)、アクチュエータ(執行)、コネクタ(コネクタ)を見つけます

protected void initInternal() throws LifecycleException {

        super.initInternal();

        if (engine != null) {
            // 初始化引擎
            engine.init();
        }

        // Initialize any Executors
        for (Executor executor : findExecutors()) {
            if (executor instanceof JmxEnabled) {
                ((JmxEnabled) executor).setDomain(getDomain());
            }
            // 初始化执行器
            executor.init();
        }

        // Initialize mapper listener
        mapperListener.init();

        // Initialize our defined Connectors
        synchronized (connectorsLock) {
            for (Connector connector : connectors) {
                try {
                    // 初始化连接器
                    connector.init();
                } catch (Exception e) {
                    String message = sm.getString(
                            "standardService.connector.initFailed", connector);
                    log.error(message, e);

                    if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
                        throw new LifecycleException(message);
                }
            }
        }
    }

2.5コネクタ

サービス内のコンポーネントの多くを初期化、これらのコンポーネントの初期化は、私たちがどのようなコネクタに焦点を当てて、ここで、似ています。

コネクタは、直接呼び出し、そのメソッドinitInternalので、インタフェースではありません。

2.5.1アダプタの作成

adapter = new CoyoteAdapter(this);

2.5.2初期化protocolHandler

try {
            protocolHandler.init();
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
        }

3.開始プロセス

ブートストラップ主な機能には、ロードメソッドstartメソッドに続いて、以下、我々はTomcatの起動プロセスに沿ってコードを見てみましょう。

daemon.start();

まず第一に、それ自体はstartメソッドを呼び出して、その後、startメソッドを呼び出しカタリナ

public void start() throws Exception {
        if (catalinaDaemon == null) {
            init();
        }

        Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
        // 调用catalina的start方法
        method.invoke(catalinaDaemon, (Object [])null);
    }

その後、カタリナのstartメソッドは、サーバーのstartメソッドを呼び出すには

try {
   getServer().start();
}

そして、それはテンプレートのデザインパターンを使用して、ビジネスロジックの実装クラスがstartInternal法による起動方法の各インターフェイスの開始実行、LifeCycleBase来ます。

ここprotocolHandlerのstartメソッドを呼び出してフォーカス、コールstartInternal方法コネクタに次のスタートコネクタコネクタオブジェクトを参照すると、

try {
  protocolHandler.start();
} 

最後に、プログラムはスタートの方法に進みますAbsTractEndpoint

public final void start() throws Exception {
        if (bindState == BindState.UNBOUND) {
            bind();
            bindState = BindState.BOUND_ON_START;
        }
        startInternal();
    }

実行startInternal()メソッドは、それがHTTP / 1.1であるので、それはこの方法の最終面でstartInternal方法NioEndpointを実行する、呼び出し元のスレッドがオープンを有します

// 开启线程
startAcceptorThreads();
protected final void startAcceptorThreads() {
        int count = getAcceptorThreadCount();
        // 接受客户端的请求对象
        acceptors = new Acceptor[count];

        // 开启线程
        for (int i = 0; i < count; i++) {
            // 创建线程对象
            acceptors[i] = createAcceptor();
            String threadName = getName() + "-Acceptor-" + i;
            acceptors[i].setThreadName(threadName);
            Thread t = new Thread(acceptors[i], threadName);
            t.setPriority(getAcceptorThreadPriority());
            t.setDaemon(getDaemon());
            t.start();
        }
    }

 createAcceptor():

protected AbstractEndpoint.Acceptor createAcceptor() {
        return new Acceptor();
    }

アクセプター():

protected class Acceptor extends AbstractEndpoint.Acceptor {

        @Override
        public void run() {

            int errorDelay = 0;

            // Loop until we receive a shutdown command
            while (running) {

                // Loop if endpoint is paused
                while (paused && running) {
                    state = AcceptorState.PAUSED;
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }

                if (!running) {
                    break;
                }
                state = AcceptorState.RUNNING;

                try {
                    //if we have reached max connections, wait
                    countUpOrAwaitConnection();

                    SocketChannel socket = null;
                    try {
                        // Accept the next incoming connection from the server
                        // socket
                        socket = serverSock.accept();
                    } catch (IOException ioe) {
                        // We didn't get a socket
                        countDownConnection();
                        if (running) {
                            // Introduce delay if necessary
                            errorDelay = handleExceptionWithDelay(errorDelay);
                            // re-throw
                            throw ioe;
                        } else {
                            break;
                        }
                    }
                    // Successful accept, reset the error delay
                    errorDelay = 0;

                    // Configure the socket
                    if (running && !paused) {
                        // setSocketOptions() will hand the socket off to
                        // an appropriate processor if successful
                        if (!setSocketOptions(socket)) {
                            closeSocket(socket);
                        }
                    } else {
                        closeSocket(socket);
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }
            }
            state = AcceptorState.ENDED;
        }

次のようにアクセプタrunメソッドは、コードワードクライアントの要求を受信するためにあります:

socket = serverSock.accept();

そして、クライアントからの要求を受信するための待機。

これまでのところ、プロセスの終了を開始!

要約:

        段階的アセンブリの初期化動作、及び呼開始のスタートフローチャートからソースの追跡、それが標準化され、起動プロセスTOMCAT見ることができる、ライフサイクル管理インタフェース定義のライフサイクルの統一開始は、最初のコールは、init()メソッド( )を開始する方法。

        我々は容易に変更及び設定ファイルに置き換えることができるため、ライフサイクル管理プロセス自体の各段階の完了に加えて構成要素だけでなく、サブアセンブリ、構成要素及び構成要素間の応答に呼び出すための責任は緩く、結合されています。

公開された128元の記事 ウォンの賞賛6 ビュー3220

おすすめ

転載: blog.csdn.net/weixin_43318134/article/details/103941160