tomcatSupplement(1)tomcat启动脚本分析(以Windows平台为例)

【0】README
1)本文部分文字描述转自:“深入剖析tomcat”,旨在学习“tomcat启动脚本分析” 的相关知识;

【1】Windows平台的启动脚本
1)分析catalina.bat 批处理文件的内容:(catalina.bat
step1)首先使用 @echo off 命令隐藏命令的显示;
step2)然后检查环境变量OS的值是否为 “Windows_NT”;即用户使用的是否是 window os 的相应distribution;如果是,它就调用 setLocal 命令将对环境变量的修改控制在当前批处理文件中:
if "%OS%" == "Windows_NT" setlocal
step3)然后,如果先前没有设置变量 CATALINA_HOME 的值,就在这里进行设置。默认case下,变量 CATALINE_HOME 是不存在的;如果显然没有设置过变量 CATALINA_HOME,那么批处理文件会猜测是从哪个文件目录进行调用;(干货——设置 环境变量CATALINA_HOME的值,该值应该被正确设置为bin的父目录)
step3.1)首先,它会假设catalina.bat 文件是在安装目录中进行调用的。那么在bin目录下就一定存在一个 catalina.bat 的文件:
if not "%CATALINA_HOME%" == "" goto gotHome
set CATALINA_HOME=.
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
step3.2)如果在当前目录的子目录bin下没有找到catalina.bat 文件;批处理文件会再猜测一次;这次,它还会假设catalina.bat 文件是在安装目录的bin 命令下调用的,但是会将变量 CATALINA_HOME 设置为当前目录的父目录,并检查 catalina.bat 是否存在于 bin目录中;
set CATALINA_HOME=..
:gotHome
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
step3.3)如果这次猜测正确,就跳转到 okHome标签所在位置继续运行;否则,它输出错误消息,告诉用户变量 CATALINA_HOME 设置错误,并跳转到end标签所在位置。end标签在批处理文件的末尾,会退出脚本执行;
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome 
step3.4)如果CATALINE_HOME 设置正确,并且setenv.bat 文件存在的话,会调用 setenv.bat 批处理脚本来设置需要的环境变量。如果 setenv.bat 文件不存在,就输出错误消息;(干货——查看setenv.bat是否存在,存在的话就调用该文件设置环境变量)
rem Get standard environment variables 
if exist "%CATALINA_HOME%\bin\setenv.bat" call "%CATALINA_HOME%\bin\setenv.bat"
step4)接下来,它检查 setclasspath.bat 是否存在?如果不存在,它输出一条错误消息,并跳转到end标签所在的位置,退出批处理文件;(干货——查看 setclasspath.bat文件是否存在,存在的话定义变量BASEDIR=%CATALINA_HOME%)setclasspath.bat
rem Get standard Java environment variables
if exist "%CATALINA_HOME%\bin\setclasspath.bat" goto okSetclasspath
echo Cannot find %CATALINA_HOME%\bin\setclasspath.bat
echo This file is needed to run this program
goto end
step4.1)如果存在,它就定义变量 BASEDIR,并赋值为环境变量 CATALINA_HOME 的值,然后,调用 setclasspath.bat 批处理文件设置类路径:
:okSetclasspath
set BASEDIR=%CATALINA_HOME%
call "%CATALINA_HOME%\bin\setclasspath.bat"
step4.2)setclasspath.bat 文件会检查环境变量 JAVA_HOME 是否设置正确,并设置将会在 catalina.bat 批处理文件中所要用到的变量:(干货——调用setclasspath.bat 设置类路径
set JAVA_ENDORSED_DIRS=%BASEDIR%\common\endorsed
set CLASSPATH=%JAVA_HOME%\lib\tools.jar
set _RUNJAVA="%JAVA_HOME%\bin\java"
set _RUNJAVAW="%JAVA_HOME%\bin\javaw"
set _RUNJDB="%JAVA_HOME%\bin\jdb"
set _RUNJAVAC="%JAVA_HOME%\bin\javac"
step5)接下来,catalina.bat 文件会检查是否安装了 Java Secure Socket Extension(JSSE),以及环境变量 JSSE_home 是否设置正确。如果存在环境变量 JSSE_HOME,将其添加到环境变量CLASSPATH中:(干货——检查JSSE_home 环境变量是否设置
if "%JSSE_HOME%" == "" goto noJsse
set CLASSPATH=%CLASSPATH%;%JSSE_HOME%\lib\jcert.jar;%JSSE_HOME%\lib\jnet.jar;%JSSE_HOME%\lib\jsse.jar
:noJsse
step5.1)如果没有设置环境变量 JSSE_HOME,批处理文件会继续执行下面的目录,将bin目录下的 bootstrap.jar 添加到 环境变量 CLASSPATH 中;
set CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\bootstrap.jar
step6)接下来,检查环境变量 CATALINA_BASE 是否设置,若没有设置则将 CATALINE_HOME的值赋给它;(干货——检查CATALINA_BASE 环境变量是否设置
if not "%CATALINA_BASE%" == "" goto gotBase
set CATALINA_BASE=%CATALINA_HOME%
:gotBase
step6.1)接着会检查变量 %CATALINA_TMPDIR% 是否设置,若没有设置的话,将其设置为 CATALINE_BASE 下的临时目录;
if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir
set CATALINA_TMPDIR=%CATALINA_BASE%\temp
:gotTmpdir
step6.2)接着,显示一些变量的值;
echo Using CATALINA_BASE:   %CATALINA_BASE%
echo Using CATALINA_HOME:   %CATALINA_HOME%
echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR%
echo Using JAVA_HOME:       %JAVA_HOME%
step7)然后,它将 在setclasspath.bat 中设置的变量 _RUNJAVA 的值赋给 _EXECJAVA。(干货——为一些环境变量赋值)
set _EXECJAVA=%_RUNJAVA%
step7.1)它再设置如下的环境变量:
set MAINCLASS=org.apache.catalina.startup.Bootstrap // 设置启动目录;
set ACTION=start
set SECURITY_POLICY_FILE=
set DEBUG_OPTS=
set JPDA=
 public static void main(String args[]) {//org.apache.catalina.startup.Bootstrap.main().

        // Set the debug flag appropriately
        for (int i = 0; i < args.length; i++)  {
            if ("-debug".equals(args[i]))
                debug = 1;
        }

        // Configure catalina.base from catalina.home if not yet set
        if (System.getProperty("catalina.base") == null)
            System.setProperty("catalina.base", getCatalinaHome());

        // Construct the class loaders we will need
        ClassLoader commonLoader = null;
        ClassLoader catalinaLoader = null;
        ClassLoader sharedLoader = null;
        try {

            File unpacked[] = new File[1];
            File packed[] = new File[1];
            File packed2[] = new File[2];
            ClassLoaderFactory.setDebug(debug);

            unpacked[0] = new File(getCatalinaHome(),
                                   "common" + File.separator + "classes");
            packed2[0] = new File(getCatalinaHome(),
                                  "common" + File.separator + "endorsed");
            packed2[1] = new File(getCatalinaHome(),
                                  "common" + File.separator + "lib");
            commonLoader =
                ClassLoaderFactory.createClassLoader(unpacked, packed2, null);

            unpacked[0] = new File(getCatalinaHome(),
                                   "server" + File.separator + "classes");
            packed[0] = new File(getCatalinaHome(),
                                 "server" + File.separator + "lib");
            catalinaLoader =
                ClassLoaderFactory.createClassLoader(unpacked, packed,
                                                     commonLoader);

            unpacked[0] = new File(getCatalinaBase(),
                                   "shared" + File.separator + "classes");
            packed[0] = new File(getCatalinaBase(),
                                 "shared" + File.separator + "lib");
            sharedLoader =
                ClassLoaderFactory.createClassLoader(unpacked, packed,
                                                     commonLoader);
        } catch (Throwable t) {

            log("Class loader creation threw exception", t);
            System.exit(1);

        }


        Thread.currentThread().setContextClassLoader(catalinaLoader);

        // Load our startup class and call its process() method
        try {

            SecurityClassLoad.securityClassLoad(catalinaLoader);

            // Instantiate a startup class instance
            if (debug >= 1)
                log("Loading startup class");
            Class startupClass =
                catalinaLoader.loadClass
                ("org.apache.catalina.startup.Catalina");
            Object startupInstance = startupClass.newInstance();

            // Set the shared extensions class loader
            if (debug >= 1)
                log("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);

            // Call the process() method
            if (debug >= 1)
                log("Calling startup class process() method");
            methodName = "process";
            paramTypes = new Class[1];
            paramTypes[0] = args.getClass();
            paramValues = new Object[1];
            paramValues[0] = args;
            method =
                startupInstance.getClass().getMethod(methodName, paramTypes);
            method.invoke(startupInstance, paramValues);

        } catch (Exception e) {
            System.out.println("Exception during startup processing");
            e.printStackTrace(System.out);
            System.exit(2);
        }

    }


step8)接着,它会检查传入的第1个参数是否是 jpda(java platform debugger architecture);(干货——判断传入的第1个参数是否是 jpda)
step8.1)如果是:就设置变量 JPDA的值为 jpda,然后检查变量 JPDA_TRANSPORT 和 变量 JPDA_ADDRESS的值,并移动参数:
if not ""%1"" == ""jpda"" goto noJpda
set JPDA=jpda
if not "%JPDA_TRANSPORT%" == "" goto gotJpdaTransport
set JPDA_TRANSPORT=dt_shmem
:gotJpdaTransport
if not "%JPDA_ADDRESS%" == "" goto gotJpdaAddress
set JPDA_ADDRESS=jdbconn
:gotJpdaAddress
shift
step8.2)大多数case下,不需要使用 JPDA,因此,第1个参数的值必须是以下几个中的一个: debug, embedded,run,start 或 stop;
:noJpda

if ""%1"" == ""debug"" goto doDebug
if ""%1"" == ""embedded"" goto doEmbedded
if ""%1"" == ""run"" goto doRun
if ""%1"" == ""start"" goto doStart
if ""%1"" == ""stop"" goto doStop
step8.3)如果第1个参数不正确,或没有使用参数,则该批处理文件会退出;
echo Usage:  catalina ( commands ... )
echo commands:
echo   debug             Start Catalina in a debugger
echo   debug -security   Debug Catalina with a security manager
echo   embedded          Start Catalina in embedded mode
echo   jpda start        Start Catalina under JPDA debugger
echo   run               Start Catalina in the current window
echo   run -security     Start in the current window with security manager
echo   start             Start Catalina in a separate window
echo   start -security   Start in a separate window with security manager
echo   stop              Stop Catalina
goto end
step9)如果参数是start,则跳转到 doStart标签后,catalina.bat(它)会调用 shift命令来检查下一个参数;如果有第2个参数的话,那么它必须是 -security;否则,忽略它;如果下一个参数是 -security,会再次调用 shift命令,变量 SECURITY_POLICY_FILE 会被设置成为 %CATALINA_BASE%\conf\catalina.policy;(干货——如果运行catalina.bat 批处理文件的参数是start)
:doStart
shift
if not "%OS%" == "Windows_NT" goto noTitle
set _EXECJAVA=start "Tomcat" %_RUNJAVA%
goto gotTitle
:noTitle
set _EXECJAVA=start %_RUNJAVA%
:gotTitle
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy
step9.1)跳转到 execCmd标签处:
goto execCmd
step9.2)execCmd标签下的 命令接收剩余未移动的命令行参数,将它们保存到 变量 CMD_LINE_ARGS 中,再跳转到 doneSetArgs 标签处:
:execCmd
rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
step9.3)下面是 doneSetArgs 标签处的代码
:doneSetArgs
rem Execute Java with the applicable properties
if not "%JPDA%" == "" goto doJpda
if not "%SECURITY_POLICY_FILE%" == "" goto doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
对以上代码的分析(Analysis): 例如在pc上,调用catalina.bat 文件,上面的代码 会被转换为下面的实际代码:(从 %_EXECJAVA% 到 %ACTION%)
start "Tomcat" "C:\jdk1.8.0_60\bin\java" -Djava.endorsed.dirs="..\common\endorsed" -classpath "C:\jdk1.8.0_60\lib\tools.jar;..\lib\bootstrap.jar" -Dcatalina.base=".." Dcatalina.home=".." -Djava.io.tmpdir="..\temp" org.apache.catalina.startup.Bootstrap start

2)分析 startup.bat 批处理文件的内容:(其他startup.bat 是调用了 catalina.bat 文件)startup.bat

2.1)鉴于startup.bat 的 内容与 catlina.bat 文件的内容相似度较大,不不做分析,仅给出其源码;

@echo off

rem   Licensed to the Apache Software Foundation (ASF) under one or more
rem   contributor license agreements.  See the NOTICE file distributed with
rem   this work for additional information regarding copyright ownership.
rem   The ASF licenses this file to You under the Apache License, Version 2.0
rem   (the "License"); you may not use this file except in compliance with
rem   the License.  You may obtain a copy of the License at
rem 
rem       http://www.apache.org/licenses/LICENSE-2.0
rem 
rem   Unless required by applicable law or agreed to in writing, software
rem   distributed under the License is distributed on an "AS IS" BASIS,
rem   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rem   See the License for the specific language governing permissions and
rem   limitations under the License.

if "%OS%" == "Windows_NT" setlocal
rem ---------------------------------------------------------------------------
rem Start script for the CATALINA Server
rem
rem $Id: startup.bat 743401 2009-02-11 17:01:58Z markt $
rem ---------------------------------------------------------------------------

rem Guess CATALINA_HOME if not defined
if not "%CATALINA_HOME%" == "" goto gotHome
set CATALINA_HOME=.
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
set CATALINA_HOME=..
:gotHome
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome

set EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat  // 设置 catalina.bat 到 EXECUTABLE.

rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find %EXECUTABLE%
echo This file is needed to run this program
goto end
:okExec

rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs

call "%EXECUTABLE%" start %CMD_LINE_ARGS% // highlight line.

:end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值