tomcat源码解析(1)
最近在学习java,在学习至jsp部分时用到了tomcat,一了解发现这个tomcat原来也是用java写的,且是开源的,这我就happy了,趁着空闲把源码下载了下来,学习,以下3编是我从别人那里复制过来的,算是做一个初步了解,至于我的一些看法和认识将在以后记载
原文地址 http://blog.csdn.net/chenxiaohua/article/details/2624997 在此谢谢博主的解惑^_^
1.
tomcat启动命令
安装tomcat之后,设置CATALINA_HOME=tomcat的安装目录,比如安装在c:/tomcat,那么CATALINA_HOME=c:/tomcat,添加路径到path环境变量,%CATALINA_HOME%/bin,然后打开控制台,进入tomcat的bin目录,这儿有tomcat的启动脚本,startup.bat启动tomcat,shutdown.bat关闭tomcat。我是在windows下做的调试,如果在linux/unix下,相应的启动脚本为startup.sh和shutdown.sh。
tomcat启动脚本解说
用文本编辑器打开startup.bat,你会看到如下,内容:
View Code1 @echo off 2 3 if "%OS%" == "Windows_NT" setlocal 4 5 rem --------------------------------------------------------------------------- 6 7 rem Start script for the CATALINA Server 8 9 rem 10 11 rem $Id: startup.bat,v 1.6 2004/05/27 18:25:11 yoavs Exp $ 12 13 rem --------------------------------------------------------------------------- 14 15 16 17 rem Guess CATALINA_HOME if not defined 18 19 set CURRENT_DIR=%cd% 20 21 if not "%CATALINA_HOME%" == "" goto gotHome 22 23 set CATALINA_HOME=%CURRENT_DIR% 24 25 if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome 26 27 cd .. 28 29 set CATALINA_HOME=%cd% 30 31 cd %CURRENT_DIR% 32 33 :gotHome 34 35 if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome 36 37 echo The CATALINA_HOME environment variable is not defined correctly 38 39 echo This environment variable is needed to run this program 40 41 goto end 42 43 :okHome 44 45 46 47 set EXECUTABLE=%CATALINA_HOME%/bin/catalina.bat 48 49 50 51 rem Check that target executable exists 52 53 if exist "%EXECUTABLE%" goto okExec 54 55 echo Cannot find %EXECUTABLE% 56 57 echo This file is needed to run this program 58 59 goto end 60 61 :okExec 62 63 64 65 rem Get remaining unshifted command line arguments and save them in the 66 67 set CMD_LINE_ARGS= 68 69 :setArgs 70 71 if ""%1""=="""" goto doneSetArgs 72 73 set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1 74 75 shift 76 77 goto setArgs 78 79 :doneSetArgs 80 81 82 83 call "%EXECUTABLE%" start %CMD_LINE_ARGS% 84 85 86 87 :end第一段,内容如下,先设置好变量CATALINA_HOME,然后判断是否存在脚本文件"%CATALINA_HOME%/bin/catalina.bat",如果找不到该文件,那么退出脚本的执行,提示设置CATALINA_HOME环境变量,这就是我们在安装tomcat后,要设置环境变量CATALINA_HOME的原因
View Code1 @echo off 2 3 if "%OS%" == "Windows_NT" setlocal 4 5 rem --------------------------------------------------------------------------- 6 7 rem Start script for the CATALINA Server 8 9 rem 10 11 rem $Id: startup.bat,v 1.6 2004/05/27 18:25:11 yoavs Exp $ 12 13 rem --------------------------------------------------------------------------- 14 15 16 17 rem Guess CATALINA_HOME if not defined 18 19 set CURRENT_DIR=%cd% 20 21 if not "%CATALINA_HOME%" == "" goto gotHome 22 23 set CATALINA_HOME=%CURRENT_DIR% 24 25 if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome 26 27 cd .. 28 29 set CATALINA_HOME=%cd% 30 31 cd %CURRENT_DIR% 32 33 :gotHome 34 35 if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome 36 37 echo The CATALINA_HOME environment variable is not defined correctly 38 39 echo This environment variable is needed to run this program 40 41 goto end 42 43 :okHome 44 45 46 47 set EXECUTABLE=%CATALINA_HOME%/bin/catalina.bat第二段,内容如下,用EXECUTABLE脚本指向的脚本文件,执行启动命令,传入参数start,既进入启动脚本catalina.bat的执行。
View Code1 rem Check that target executable exists 2 3 if exist "%EXECUTABLE%" goto okExec 4 5 echo Cannot find %EXECUTABLE% 6 7 echo This file is needed to run this program 8 9 goto end 10 11 :okExec 12 13 14 15 rem Get remaining unshifted command line arguments and save them in the 16 17 set CMD_LINE_ARGS= 18 19 :setArgs 20 21 if ""%1""=="""" goto doneSetArgs 22 23 set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1 24 25 shift 26 27 goto setArgs 28 29 :doneSetArgs 30 31 32 33 call "%EXECUTABLE%" start %CMD_LINE_ARGS% 34 35 36 37 :endcatalina.bat内容如下:
View Code1 @echo off 2 3 if "%OS%" == "Windows_NT" setlocal 4 5 rem --------------------------------------------------------------------------- 6 7 rem Start/Stop Script for the CATALINA Server 8 9 rem 10 11 rem Environment Variable Prequisites 12 13 rem 14 15 rem CATALINA_HOME May point at your Catalina "build" directory. 16 17 rem 18 19 rem CATALINA_BASE (Optional) Base directory for resolving dynamic portions 20 21 rem of a Catalina installation. If not present, resolves to 22 23 rem the same directory that CATALINA_HOME points to. 24 25 rem 26 27 rem CATALINA_OPTS (Optional) Java runtime options used when the "start", 28 29 rem "stop", or "run" command is executed. 30 31 rem 32 33 rem CATALINA_TMPDIR (Optional) Directory path location of temporary directory 34 35 rem the JVM should use (java.io.tmpdir). Defaults to 36 37 rem %CATALINA_BASE%/temp. 38 39 rem 40 41 rem JAVA_HOME Must point at your Java Development Kit installation. 42 43 rem 44 45 rem JAVA_OPTS (Optional) Java runtime options used when the "start", 46 47 rem "stop", or "run" command is executed. 48 49 rem 50 51 rem JSSE_HOME (Optional) May point at your Java Secure Sockets Extension 52 53 rem (JSSE) installation, whose JAR files will be added to the 54 55 rem system class path used to start Tomcat. 56 57 rem 58 59 rem JPDA_TRANSPORT (Optional) JPDA transport used when the "jpda start" 60 61 rem command is executed. The default is "dt_shmem". 62 63 rem 64 65 rem JPDA_ADDRESS (Optional) Java runtime options used when the "jpda start" 66 67 rem command is executed. The default is "jdbconn". 68 69 rem 70 71 rem $Id: catalina.bat,v 1.9.2.2 2004/09/23 20:17:14 yoavs Exp $ 72 73 rem --------------------------------------------------------------------------- 74 75 76 77 rem Guess CATALINA_HOME if not defined 78 79 set CURRENT_DIR=%cd% 80 81 if not "%CATALINA_HOME%" == "" goto gotHome 82 83 set CATALINA_HOME=%CURRENT_DIR% 84 85 if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome 86 87 cd .. 88 89 set CATALINA_HOME=%cd% 90 91 cd %CURRENT_DIR% 92 93 :gotHome 94 95 if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome 96 97 echo The CATALINA_HOME environment variable is not defined correctly 98 99 echo This environment variable is needed to run this program 100 101 goto end 102 103 :okHome 104 105 106 107 rem Get standard environment variables 108 109 if exist "%CATALINA_HOME%/bin/setenv.bat" call "%CATALINA_HOME%/bin/setenv.bat" 110 111 112 113 rem Get standard Java environment variables 114 115 if exist "%CATALINA_HOME%/bin/setclasspath.bat" goto okSetclasspath 116 117 echo Cannot find %CATALINA_HOME%/bin/setclasspath.bat 118 119 echo This file is needed to run this program 120 121 goto end 122 123 :okSetclasspath 124 125 set BASEDIR=%CATALINA_HOME% 126 127 call "%CATALINA_HOME%/bin/setclasspath.bat" 128 129 130 131 rem Add on extra jar files to CLASSPATH 132 133 if "%JSSE_HOME%" == "" goto noJsse 134 135 set CLASSPATH=%CLASSPATH%;%JSSE_HOME%/lib/jcert.jar;%JSSE_HOME%/lib/jnet.jar;%JSSE_HOME%/lib/jsse.jar 136 137 :noJsse 138 139 set CLASSPATH=%CLASSPATH%;%CATALINA_HOME%/bin/bootstrap.jar 140 141 142 143 if not "%CATALINA_BASE%" == "" goto gotBase 144 145 set CATALINA_BASE=%CATALINA_HOME% 146 147 :gotBase 148 149 150 151 if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir 152 153 set CATALINA_TMPDIR=%CATALINA_BASE%/temp 154 155 :gotTmpdir 156 157 158 159 rem ----- Execute The Requested Command --------------------------------------- 160 161 162 163 echo Using CATALINA_BASE: %CATALINA_BASE% 164 165 echo Using CATALINA_HOME: %CATALINA_HOME% 166 167 echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR% 168 169 echo Using JAVA_HOME: %JAVA_HOME% 170 171 172 173 set _EXECJAVA=%_RUNJAVA% 174 175 set MAINCLASS=org.apache.catalina.startup.Bootstrap 176 177 set ACTION=start 178 179 set SECURITY_POLICY_FILE= 180 181 set DEBUG_OPTS= 182 183 set JPDA= 184 185 186 187 if not ""%1"" == ""jpda"" goto noJpda 188 189 set JPDA=jpda 190 191 if not "%JPDA_TRANSPORT%" == "" goto gotJpdaTransport 192 193 set JPDA_TRANSPORT=dt_shmem 194 195 :gotJpdaTransport 196 197 if not "%JPDA_ADDRESS%" == "" goto gotJpdaAddress 198 199 set JPDA_ADDRESS=jdbconn 200 201 :gotJpdaAddress 202 203 shift 204 205 :noJpda 206 207 208 209 if ""%1"" == ""debug"" goto doDebug 210 211 if ""%1"" == ""run"" goto doRun 212 213 if ""%1"" == ""start"" goto doStart 214 215 if ""%1"" == ""stop"" goto doStop 216 217 if ""%1"" == ""version"" goto doVersion 218 219 220 221 echo Usage: catalina ( commands ... ) 222 223 echo commands: 224 225 echo debug Start Catalina in a debugger 226 227 echo debug -security Debug Catalina with a security manager 228 229 echo jpda start Start Catalina under JPDA debugger 230 231 echo run Start Catalina in the current window 232 233 echo run -security Start in the current window with security manager 234 235 echo start Start Catalina in a separate window 236 237 echo start -security Start in a separate window with security manager 238 239 echo stop Stop Catalina 240 241 echo version What version of tomcat are you running? 242 243 goto end 244 245 246 247 :doDebug 248 249 shift 250 251 set _EXECJAVA=%_RUNJDB% 252 253 set DEBUG_OPTS=-sourcepath "%CATALINA_HOME%/../../jakarta-tomcat-catalina/catalina/src/share" 254 255 if not ""%1"" == ""-security"" goto execCmd 256 257 shift 258 259 echo Using Security Manager 260 261 set SECURITY_POLICY_FILE=%CATALINA_BASE%/conf/catalina.policy 262 263 goto execCmd 264 265 266 267 :doRun 268 269 shift 270 271 if not ""%1"" == ""-security"" goto execCmd 272 273 shift 274 275 echo Using Security Manager 276 277 set SECURITY_POLICY_FILE=%CATALINA_BASE%/conf/catalina.policy 278 279 goto execCmd 280 281 282 283 :doStart 284 285 shift 286 287 if not "%OS%" == "Windows_NT" goto noTitle 288 289 set _EXECJAVA=start "Tomcat" %_RUNJAVA% 290 291 goto gotTitle 292 293 :noTitle 294 295 set _EXECJAVA=start %_RUNJAVA% 296 297 :gotTitle 298 299 if not ""%1"" == ""-security"" goto execCmd 300 301 shift 302 303 echo Using Security Manager 304 305 set SECURITY_POLICY_FILE=%CATALINA_BASE%/conf/catalina.policy 306 307 goto execCmd 308 309 310 311 :doStop 312 313 shift 314 315 set ACTION=stop 316 317 goto execCmd 318 319 320 321 :doVersion 322 323 %_EXECJAVA% -classpath "%CATALINA_HOME%/server/lib/catalina.jar" org.apache.catalina.util.ServerInfo 324 325 goto end 326 327 328 329 330 331 :execCmd 332 333 rem Get remaining unshifted command line arguments and save them in the 334 335 set CMD_LINE_ARGS= 336 337 :setArgs 338 339 if ""%1""=="""" goto doneSetArgs 340 341 set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1 342 343 shift 344 345 goto setArgs 346 347 :doneSetArgs 348 349 350 351 rem Execute Java with the applicable properties 352 353 if not "%JPDA%" == "" goto doJpda 354 355 if not "%SECURITY_POLICY_FILE%" == "" goto doSecurity 356 357 %_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% 358 359 goto end 360 361 :doSecurity 362 363 %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION% 364 365 goto end 366 367 :doJpda 368 369 if not "%SECURITY_POLICY_FILE%" == "" goto doSecurityJpda 370 371 %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% -Xdebug -Xrunjdwp:transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=n %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% 372 373 goto end 374 375 :doSecurityJpda 376 377 %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% -Xdebug -Xrunjdwp:transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=n %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION% 378 379 goto end 380 381 382 383 :end解释,1。再次验证catalina.bat;2。调用setclasspath.bat设置java虚拟机相关的环境变量,所以在运行tomcat的前,一定要先安装jdk,并设置好JAVA_HOME环境变量;3。设置启动程序,添加CLASSPATH,bootstrap.jar,和启动类org.apache.catalina.startup.Bootstrap;4。最后执行虚拟机,运行tomcat。运行tomcat的参数行为%_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%,在我的电脑上调试,将所有的变量内容转译出来,执行的命令即为:start "Tomcat" "C:/j2sdk1.4.2_15/bin/java" -Djava.endorsed.dirs="C:/Tomcat 5.0/common/endorsed" -classpath "C:/j2sdk1.4.2_15/lib/tools.jar;C:/Tomcat 5.0/bin/bootstrap.jar" -Dcatalina.base="C:/Tomcat 5.0" -Dcatalina.home="C:/Tomcat 5.0" -Djava.io.tmpdir="C:/Tomcat 5.0/temp" org.apache.catalina.startup.Bootstrap start
在该命令中,start "Tomcat"是在控制态打开一个新的窗口,然后运行java虚拟机C:/j2sdk1.4.2_15/bin/java,现在大家应该明白了,tomcat是从bootstrap.jar中的org.apache.catalina.startup.Bootstrap类的main函数开始启动运行,并且传入了start参数。-D开始的都是虚拟机的运行参数。
用winrar打开bootstrap.jar打开,在META-INF目录下打开MANIFEST.MF,你会看到如下内容: Manifest-Version: 1.0 Ant-Version: Apache Ant 1.6.1 Created-By: 1.4.2-b28 (Sun Microsystems Inc.) Main-Class: org.apache.catalina.startup.Bootstrap Specification-Title: Catalina Specification-Version: 1.0 Class-Path: jmx.jar commons-daemon.jar commons-logging-api.jar 指定了该jar包从那个类开始运行,依赖那些jar包。
结论
通过对脚本的研究,我们应该知道,tomcat从那儿开始运行,只有有了运行的线索,那么我们就可以从头开始调试tomcat源代码。调试tomcat源代码的准备工作,从www.apache.org上下载相应版本,带源代码的安装程序,并安装。
2.
1。准备工作
下载tomcat,我下载的是tomcat5.0.30,我认为这是一个比较好的版本。下载地址http://archive.apache.org/dist/tomcat/tomcat-5/v5.0.30/bin/,选择window下载安装文件。
安装的时候,选择安装源代码选项,如下图。我的tomcat安装目录是C:/Tomcat 5.0
安装myeclipse,我安装的是5.5版。
2。创建工程
tomcat的整个安装目录拷贝到myeclipse的workspace目录下,如下图:
然后创建一个名为Tomcat 5.0的java project,如下步骤。
第一步,选择创建project,如下图:
第二步,选择java project:
第三步,选择和tomcat拷贝目录同名的project,如下图,选择“Finish”按钮。
这时候,你已经创建了tomcat的调试环境。
你可能会看到一些红色编译错误,你还需要下载mail.jar,activation.jar两个库文件,添加到工程中。
工程中估计还有一些编译错误,大家可以自己修改代码来解决,应该很简单。
3。开始调试
打开文件Bootstrap.java,所在的包为package org.apache.catalina.startup,如下图:
这就是tomcat的启动文件(大家可以通过文件搜索来找到该文件所在路径),找到main方法,tomcat就从这个main方法的地方开始运行启动,你现在可以设置断点,开始运行。
由于时间的原因,我都写的比较检阅,如果对myeclipse和tomcat有一定了解的朋友,肯定能很快建立环境。
3.
有了上面的准备工作,我们开始源代码调试。
main函数说明
开打Bootstrap.java,找到main函数,函数源代码如下:
- public static void main(String args[]) {
- try {
- // Attempt to load JMX class
- new ObjectName("test:foo=bar");
- } catch (Throwable t) {
- System.out.println(JMX_ERROR_MESSAGE);
- try {
- // Give users some time to read the message before exiting
- Thread.sleep(5000);
- } catch (Exception ex) {
- }
- return;
- }
- 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[0] = "start";
- daemon.load(args);
- daemon.start();
- } else if (command.equals("stopd")) {
- args[0] = "stop";
- daemon.stop();
- } else if (command.equals("start")) {
- daemon.setAwait(true);
- daemon.load(args);
- daemon.start();
- } else if (command.equals("stop")) {
- daemon.stopServer(args);
- }
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
public static void main(String args[]) { try { // Attempt to load JMX class new ObjectName("test:foo=bar"); } catch (Throwable t) { System.out.println(JMX_ERROR_MESSAGE); try { // Give users some time to read the message before exiting Thread.sleep(5000); } catch (Exception ex) { } return; } 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[0] = "start"; daemon.load(args); daemon.start(); } else if (command.equals("stopd")) { args[0] = "stop"; daemon.stop(); } else if (command.equals("start")) { daemon.setAwait(true); daemon.load(args); daemon.start(); } else if (command.equals("stop")) { daemon.stopServer(args); } } catch (Throwable t) { t.printStackTrace(); } }上面的代码一共分成三部分: 第一部分:
- try {
- // Attempt to load JMX class
- new ObjectName("test:foo=bar");
- } catch (Throwable t) {
- System.out.println(JMX_ERROR_MESSAGE);
- try {
- // Give users some time to read the message before exiting
- Thread.sleep(5000);
- } catch (Exception ex) {
- }
- return;
- }
try { // Attempt to load JMX class new ObjectName("test:foo=bar"); } catch (Throwable t) { System.out.println(JMX_ERROR_MESSAGE); try { // Give users some time to read the message before exiting Thread.sleep(5000); } catch (Exception ex) { } return; }验证jdk基础类是否载入,没有载入,在标准输入打印错误信息,然后退出程序运行。
第二部分:
- if (daemon == null) {
- daemon = new Bootstrap();
- try {
- daemon.init();
- } catch (Throwable t) {
- t.printStackTrace();
- return;
- }
- }
if (daemon == null) { daemon = new Bootstrap(); try { daemon.init(); } catch (Throwable t) { t.printStackTrace(); return; } }初始化运行环境,载入需要的jar包,读取conf/server.xml,生成相应的运行对象:
第三部分:
- try {
- String command = "start";
- if (args.length > 0) {
- command = args[args.length - 1];
- }
- if (command.equals("startd")) {
- args[0] = "start";
- daemon.load(args);
- daemon.start();
- } else if (command.equals("stopd")) {
- args[0] = "stop";
- daemon.stop();
- } else if (command.equals("start")) {
- daemon.setAwait(true);
- daemon.load(args);
- daemon.start();
- } else if (command.equals("stop")) {
- daemon.stopServer(args);
- }
- } catch (Throwable t) {
- t.printStackTrace();
- }
try { String command = "start"; if (args.length > 0) { command = args[args.length - 1]; } if (command.equals("startd")) { args[0] = "start"; daemon.load(args); daemon.start(); } else if (command.equals("stopd")) { args[0] = "stop"; daemon.stop(); } else if (command.equals("start")) { daemon.setAwait(true); daemon.load(args); daemon.start(); } else if (command.equals("stop")) { daemon.stopServer(args); } } catch (Throwable t) { t.printStackTrace(); }装载,开始运行。

浙公网安备 33010602011771号