Tomcat啟動分析(一)-從腳本到main函數分析


當我們在Linux下啟動tomcat的時候,通過ps查看其進程信息為,接下來的內容我們就以此進行分析:

[tomcat@fdd ~]$ ps -ef |grep java
tomcat    1521     1 18 23:20 tty1     00:00:09 /usr/bin/java -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-7.0.69/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/home/tomcat/apache-tomcat-7.0.69/endorsed -classpath /home/tomcat/apache-tomcat-7.0.69/bin/bootstrap.jar:/home/tomcat/apache-tomcat-7.0.69/bin/tomcat-juli.jar -Dcatalina.base=/home/tomcat/apache-tomcat-7.0.69 -Dcatalina.home=/home/tomcat/apache-tomcat-7.0.69 -Djava.io.tmpdir=/home/tomcat/apache-tomcat-7.0.69/temp org.apache.catalina.startup.Bootstrap start

 

1 startup.sh分析

我們啟動Tomcat的時候,執行的是sh startup.sh,那么在startup.sh中做了哪些事情呢,實際上就是調用catalina.sh,具體過程請看下面分析

……
# 指定Tomcat路徑
PRGDIR=`dirname "$PRG"`
# 指定調用腳本
EXECUTABLE=catalina.sh
……
# 執行啟動腳本
exec "$PRGDIR"/"$EXECUTABLE" start "$@"

2. catalina.sh分析

在catalina.sh中完成環境檢查、環境初始化、參數初始化、啟動操作,也就是在這個里面利用JVM中的java命令執行tomcat的main方法的:

……
# 環境檢查
case $CATALINA_HOME in
  *:*) echo "Using CATALINA_HOME:   $CATALINA_HOME";
       echo "Unable to start as CATALINA_HOME contains a colon (:) character";
       exit 1;
esac
case $CATALINA_BASE in
  *:*) echo "Using CATALINA_BASE:   $CATALINA_BASE";
       echo "Unable to start as CATALINA_BASE contains a colon (:) character";
       exit 1;
esac
……
# 初始化環境信息、參數初始化
if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
  . "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
  . "$CATALINA_HOME/bin/setenv.sh"
fi
……
# 啟動Tomcat,支持
  if [ "$1" = "-security" ] ; then
    if [ $have_tty -eq 1 ]; then
      echo "Using Security Manager"
    fi
    shift
    eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
      -Djava.security.manager \
      -Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap "$@" start \
      >> "$CATALINA_OUT" 2>&1 "&"

  else
    eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap "$@" start \
      >> "$CATALINA_OUT" 2>&1 "&"

  fi
……

3 Bootstrap分析

通過第二章節,我們可以看出實際上調用的是 java org.apache.catalina.startup.Bootstrap這個類,那么我們就來分析一下這個類

3.1 靜態代碼

類中的靜態代碼塊完成一些參數初始化:

static {
        // Will always be non-null
        String userDir = System.getProperty("user.dir");

        // Home first
        String home = System.getProperty(Globals.CATALINA_HOME_PROP);
        File homeFile = null;

        if (home != null) {
            File f = new File(home);
            try {
                homeFile = f.getCanonicalFile();
            } catch (IOException ioe) {
                homeFile = f.getAbsoluteFile();
            }
        }

        if (homeFile == null) {
            // First fall-back. See if current directory is a bin directory
            // in a normal Tomcat install
            File bootstrapJar = new File(userDir, "bootstrap.jar");

            if (bootstrapJar.exists()) {
                File f = new File(userDir, "..");
                try {
                    homeFile = f.getCanonicalFile();
                } catch (IOException ioe) {
                    homeFile = f.getAbsoluteFile();
                }
            }
        }

        if (homeFile == null) {
            // Second fall-back. Use current directory
            File f = new File(userDir);
            try {
                homeFile = f.getCanonicalFile();
            } catch (IOException ioe) {
                homeFile = f.getAbsoluteFile();
            }
        }

        catalinaHomeFile = homeFile;
        System.setProperty(
                Globals.CATALINA_HOME_PROP, catalinaHomeFile.getPath());

        // Then base
        String base = System.getProperty(Globals.CATALINA_BASE_PROP);
        if (base == null) {
            catalinaBaseFile = catalinaHomeFile;
        } else {
            File baseFile = new File(base);
            try {
                baseFile = baseFile.getCanonicalFile();
            } catch (IOException ioe) {
                baseFile = baseFile.getAbsoluteFile();
            }
            catalinaBaseFile = baseFile;
        }
        System.setProperty(
                Globals.CATALINA_BASE_PROP, catalinaBaseFile.getPath());
    }

3.2 調用main方法

main方法是啟動一個java程序的入口,任何程序都會有自己的main方法,tomcat是一個WEB容器,也不例外:

public static void main(String args[]) {
       //如果守護進程為空,則進行初始化
        if (daemon == null) {
            // Don't set daemon until init() has completed
            Bootstrap bootstrap = new Bootstrap();
            try {
                //初始化守護進程,初始化內容參考3.2.1
                bootstrap.init();
            } catch (Throwable t) {
                handleThrowable(t);
                t.printStackTrace();
                return;
            }
            daemon = bootstrap;
        } else {
            // When running as a service the call to stop will be on a new
            // thread so make sure the correct class loader is used to prevent
            // a range of class not found exceptions.
            Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
        }

        try {
            //判斷執行命令,並進行相應操作
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

            if (command.equals("startd")) {
                args[args.length - 1] = "start";
                //加載啟動參數,參考3.2.2
                daemon.load(args);
                //啟動Tomcat,參考3.2.3
                daemon.start();
            } else if (command.equals("stopd")) {
                args[args.length - 1] = "stop";
                //停止Tomcat守護進程,參考3.2.4
                daemon.stop();
            } else if (command.equals("start")) {
                daemon.setAwait(true);
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stop")) {
                //單獨停止Tomcat服務器,參考3.2.5
                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.");
            }
        } catch (Throwable t) {
            // Unwrap the Exception for clearer error reporting
            if (t instanceof InvocationTargetException &&
                    t.getCause() != null) {
                t = t.getCause();
            }
            handleThrowable(t);
            t.printStackTrace();
            System.exit(1);
        }

    }

3.2.1 初始化守護進程

此部分完成類加載器初始化

public void init() throws Exception {
        //初始化類加載器,根據catalina.properties中的加載項進行類加載
        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;

    }

3.3.2 加載啟動參數

在啟動腳本中,增加了各種啟動參數,此部分就完成這些參數的利用。

//實際調用org.apache.catalina.startup.Catalina類中的load方法
    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);

    }

接下來,我們看具體的load

//org.apache.catalina.startup.Catalina.load(String[] args)
    public void load(String args[]) {

        try {
            //參數檢查
            if (arguments(args)) {
                //加載參數
                load();
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }

//org.apache.catalina.startup.Catalina.load()
    public void load() {

        long t1 = System.nanoTime();
        //檢查臨時目錄
        initDirs();

        // Before digester - it may be needed
        initNaming();

        // Create and execute our Digester
        // 初始化XML解析器,參考:http://blog.csdn.net/u011545486/article/details/52005412
        Digester digester = createStartDigester();

        InputSource inputSource = null;
        InputStream inputStream = null;
        File file = null;
        try {
            try {
                //獲取server.xml配置文件
                file = configFile(); //通過new File()方式讀取文件
                inputStream = new FileInputStream(file);
                inputSource = new InputSource(file.toURI().toURL().toString());
            } catch (Exception e) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("catalina.configFail", file), e);
                }
            }
            if (inputStream == null) { //讀取失敗,則通過getResource方式讀取文件
                try {
                    inputStream = getClass().getClassLoader()
                        .getResourceAsStream(getConfigFile());
                    inputSource = new InputSource
                        (getClass().getClassLoader()
                         .getResource(getConfigFile()).toString());
                } catch (Exception e) {
                    if (log.isDebugEnabled()) {
                        log.debug(sm.getString("catalina.configFail",
                                getConfigFile()), e);
                    }
                }
            }

            // This should be included in catalina.jar
            // Alternative: don't bother with xml, just create it manually.
            if (inputStream == null) { //如果沒有server.xml配置文件,則采用jar包中自帶的server-embed.xml
                try {
                    inputStream = getClass().getClassLoader()
                            .getResourceAsStream("server-embed.xml");
                    inputSource = new InputSource
                    (getClass().getClassLoader()
                            .getResource("server-embed.xml").toString());
                } catch (Exception e) {
                    if (log.isDebugEnabled()) {
                        log.debug(sm.getString("catalina.configFail",
                                "server-embed.xml"), e);
                    }
                }
            }


            if (inputStream == null || inputSource == null) { //仍不存在,則進行警告處理,並結束啟動
                if  (file == null) {
                    log.warn(sm.getString("catalina.configFail",
                            getConfigFile() + "] or [server-embed.xml]"));
                } else {
                    log.warn(sm.getString("catalina.configFail",
                            file.getAbsolutePath()));
                    if (file.exists() && !file.canRead()) {
                        log.warn("Permissions incorrect, read permission is not allowed on the file.");
                    }
                }
                return;
            }

            try {
                //解析XML配置
                inputSource.setByteStream(inputStream);
                digester.push(this);
                digester.parse(inputSource);
            } catch (SAXParseException spe) {
                log.warn("Catalina.start using " + getConfigFile() + ": " +
                        spe.getMessage());
                return;
            } catch (Exception e) {
                log.warn("Catalina.start using " + getConfigFile() + ": " , e);
                return;
            }
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    // Ignore
                }
            }
        }
        //設置catalina屬性
        getServer().setCatalina(this);
        getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
        getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());

        // Stream redirection
        // 設置日志輸出流
        initStreams();

        // Start the new server
        try {
            //實際調用的是: org.apache.catalina.util.LifecycleBase.init()
            //啟動Tomcat
            getServer().init();
        } catch (LifecycleException e) {
            if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
                throw new java.lang.Error(e);
            } else {
                log.error("Catalina.start", e);
            }
        }

        long t2 = System.nanoTime();
        if(log.isInfoEnabled()) {
            log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
        }
    }

3.2.3 啟動Server

完成參數服務初始化之后,就可以進行Server啟動。主要包含兩部分:Service啟動和Server啟動。啟動過程具體處理在org.apache.catalina.util.LifecycleBase.start()中完成,然后調用org.apache.catalina.core.StandardServer.startInternal()方法進行具體的啟動操作

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++) {

                //啟動Service
                services[i].start();
            }
        }
    }

3.2.4 停止Tomcat守護進程

此實現過程在org.apache.catalina.startup.Catalina.stop()實現。

public void stop() {

        try {
            // Remove the ShutdownHook first so that server.stop()
            // doesn't get invoked twice
            if (useShutdownHook) {
                Runtime.getRuntime().removeShutdownHook(shutdownHook);

                // If JULI is being used, re-enable JULI's shutdown to ensure
                // log messages are not lost
                LogManager logManager = LogManager.getLogManager();
                if (logManager instanceof ClassLoaderLogManager) {
                    ((ClassLoaderLogManager) logManager).setUseShutdownHook(
                            true);
                }
            }
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            // This will fail on JDK 1.2. Ignoring, as Tomcat can run
            // fine without the shutdown hook.
        }

        // Shut down the server
        try {
            //獲取服務
            Server s = getServer();
            LifecycleState state = s.getState();
            if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
                    && LifecycleState.DESTROYED.compareTo(state) >= 0) {
                // Nothing to do. stop() was already called
            } else {
                //停止服務
                s.stop();
                s.destroy();
            }
        } catch (LifecycleException e) {
            log.error("Catalina.stop", e);
        }

    }

3.2.5 單獨停止Tomcat服務

此實現在org.apache.catalina.startup.Catalina.stopServer(String[] arguments)

public void stopServer(String[] arguments) {

        if (arguments != null) {
            arguments(arguments);
        }
        //獲取Server
        Server s = getServer();
        if (s == null) {
            // Create and execute our Digester
            Digester digester = createStopDigester();
            File file = configFile();
            //如果不存在,則通過配置文件獲取Server信息
            try (FileInputStream fis = new FileInputStream(file)) {
                InputSource is =
                    new InputSource(file.toURI().toURL().toString());
                is.setByteStream(fis);
                digester.push(this);
                digester.parse(is);
            } catch (Exception e) {
                log.error("Catalina.stop: ", e);
                System.exit(1);
            }
        } else {
            // Server object already present. Must be running as a service
            try {
                //停止服務
                s.stop();
            } catch (LifecycleException e) {
                log.error("Catalina.stop: ", e);
            }
            return;
        }

        // Stop the existing server
        s = getServer();
        if (s.getPort()>0) {
            //通過SOCKET通訊發起停止指令
            try (Socket socket = new Socket(s.getAddress(), s.getPort());
                    OutputStream stream = socket.getOutputStream()) {
                String shutdown = s.getShutdown();
                for (int i = 0; i < shutdown.length(); i++) {
                    stream.write(shutdown.charAt(i));
                }
                stream.flush();
            } catch (ConnectException ce) {
                log.error(sm.getString("catalina.stopServer.connectException",
                                       s.getAddress(),
                                       String.valueOf(s.getPort())));
                log.error("Catalina.stop: ", ce);
                System.exit(1);
            } catch (IOException e) {
                log.error("Catalina.stop: ", e);
                System.exit(1);
            }
        } else {
            log.error(sm.getString("catalina.stopServer"));
            System.exit(1);
        }
    }

通過對比發現,stop()方法與stopServer()方法的區別在於,stop()在執行停止的后,同時進行destroy()操作,而stopServer()並沒有發起destory操作。

同時我們可以通過Socket通訊進行關閉Tomcat,在Server.xml中配置了<Server port="8005" shutdown="SHUTDOWN">,那么Tomcat就會開啟8005端口,我們可以執行

telnet x.x.x.x 8005

輸入: SHUTDOWN

就會發現Tomcat停止了。

那么愛思考的小伙伴就會考慮了,這樣豈不是很不安全,如果別人惡意訪問我的8005端口,然后發送SHUTDOWN,那我的Tomcat豈不是就給停掉了,這樣風險太大了。

放心吧,Tomcat監聽的8005端口是監聽127.0.0.1的8005端口而不是所有IP的8005端口,除了本機可以訪問,其他電腦是不可訪問的。

#查看8005端口
C:\Users\FDD>netstat -an|findstr 8005
  TCP    127.0.0.1:8005         0.0.0.0:0              LISTENING

#查看8080端口
C:\Users\FDD>netstat -an|findstr 8080
  TCP    0.0.0.0:8080           0.0.0.0:0              LISTENING
  TCP    192.168.0.115:52201    58.251.100.102:8080    ESTABLISHED

#通過對比可發現,8005是掛在127.0.0.1的,而8080是掛在0.0.0.0(表示本機的所有IP)的

附錄:

 

一、Catalina生命周期

Common interface for component life cycle methods. Catalina components may implement this interface (as well as the appropriate interface(s) for the functionality they support) in order to provide a consistent mechanism to start and stop the component.
The valid state transitions for components that support Lifecycle are:

            start()
  -----------------------------
  |                           |
  | init()                    |
 NEW -»-- INITIALIZING        |
 | |           |              |     ------------------«-----------------------
 | |           |auto          |     |                                        |
 | |          \|/    start() \|/   \|/     auto          auto         stop() |
 | |      INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»---  |
 | |         |                                                            |  |
 | |destroy()|                                                            |  |
 | --»-----«--    ------------------------«--------------------------------  ^
 |     |          |                                                          |
 |     |         \|/          auto                 auto              start() |
 |     |     STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
 |    \|/                               ^                     |  ^
 |     |               stop()           |                     |  |
 |     |       --------------------------                     |  |
 |     |       |                                              |  |
 |     |       |    destroy()                       destroy() |  |
 |     |    FAILED ----»------ DESTROYING ---«-----------------  |
 |     |                        ^     |                          |
 |     |     destroy()          |     |auto                      |
 |     --------»-----------------    \|/                         |
 |                                 DESTROYED                     |
 |                                                               |
 |                            stop()                             |
 ----»-----------------------------»------------------------------

 Any state can transition to FAILED.

 Calling start() while a component is in states STARTING_PREP, STARTING or
 STARTED has no effect.

 Calling start() while a component is in state NEW will cause init() to be
 called immediately after the start() method is entered.

 Calling stop() while a component is in states STOPPING_PREP, STOPPING or
 STOPPED has no effect.

 Calling stop() while a component is in state NEW transitions the component
 to STOPPED. This is typically encountered when a component fails to start and
 does not start all its sub-components. When the component is stopped, it will
 try to stop all sub-components - even those it didn't start.

二、Tomcat 啟動日志

Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server version:        Apache Tomcat/7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server built:          Apr 11 2016 07:57:09 UTC
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Server number:         7.0.69.0
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: OS Name:               Linux
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: OS Version:            2.6.32-642.11.1.el6.x86_64
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Architecture:          amd64
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Java Home:             /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.121.x86_64/jre
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: JVM Version:           1.7.0_121-mockbuild_2016_11_11_19_18-b00
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: JVM Vendor:            Oracle Corporation
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: CATALINA_BASE:         /home/tomcat/apache-tomcat-7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: CATALINA_HOME:         /home/tomcat/apache-tomcat-7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-7.0.69/conf/logging.properties
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.endorsed.dirs=/home/tomcat/apache-tomcat-7.0.69/endorsed
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcatalina.base=/home/tomcat/apache-tomcat-7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Dcatalina.home=/home/tomcat/apache-tomcat-7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.VersionLoggerListener log
INFO: Command line argument: -Djava.io.tmpdir=/home/tomcat/apache-tomcat-7.0.69/temp
Jan 26, 2016 11:20:31 PM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
Jan 26, 2016 11:20:31 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Jan 26, 2016 11:20:31 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 8801 ms

至此Catalina服務已經初始化完畢,接下來就是啟動Service、Server

Jan 26, 2016 11:20:31 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Jan 26, 2016 11:20:31 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.69
Jan 26, 2016 11:20:31 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/host-manager
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/host-manager has finished in 3,197 ms
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/manager
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/manager has finished in 223 ms
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/ROOT
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/ROOT has finished in 103 ms
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/docs
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/docs has finished in 204 ms
Jan 26, 2016 11:20:35 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/examples
Jan 26, 2016 11:20:37 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /home/tomcat/apache-tomcat-7.0.69/webapps/examples has finished in 1,425 ms
Jan 26, 2016 11:20:37 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Jan 26, 2016 11:20:37 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Jan 26, 2016 11:20:37 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 5455 ms

參考資料:

[1] Tomcat啟動過程分析(上)

[2] Tomcat啟動過程分析(下)

[3]http://www.cnblogs.com/jiaan-geng/category/741736.html

[4]http://blog.csdn.net/beliefer/article/details/51035923


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM