-
main方法
-
第一阶段
-
第二阶段
-
第三阶段
-
启动参数的区别
-
一个Bug
-
configtest启动参数
一般,我们直接运行startup.sh
来
启动Tomcat
。最终执行的命令是:
java [options] org.apache.catalina.startup.Bootstrap start
options是JVM启动参数,这里忽略。
main方法
可见,Tomcat
的启动类是org.apache.catalina.startup.Bootstrap
,
启动参数是start
。我们从该类的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);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
上述代码主要分为三段:
- 第一段是检查JMX
支持
- 第二段创建Boostrap
实
例并初始化
- 第三段根据启动参数,执行进一步操作
第一阶段
乍一看,第一段似乎可有可无。它只是创
建了一个不被使用的ObjectName
对象,如果创建失败,就打印一条错误信息。而
且在Tomcat 6
中,已经移除了这段代码。
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;
}
这段代码的作用是什么呢?这其实和J2SE
1.4
的兼容性有关。Tomcat 5
使用JMX
作为管理和监控机制,但是J2SE
1.4
本身并不支持JMX
,像ObjectName
这些JMX
类
并不包括J2SE 1.4
的API
中。因此,Tomcat 5
不能直接运行
在J2SE 1.4
及之前版本上。
但是Tomcat 5
的设计目标是支持运行在J2SE 1.4
上的。因此,要达到这个目标,Tomcat 5
须
将JMX
类作为兼容包(compatibility
package
)额外添加到Tomcat
启动类路径中。
我
们有两种方法获得兼容包:
- 从Tomcat
的官方下载
页面下载兼容包,参见http://tomcat.apache.org/download-55.cgi
- 从Tomcat
的源代码构建兼容包,参见http://jarfield.iteye.com/blog/604198
不
管怎样,Tomcat 5
不能保证用户安装了兼容包,因此在启动时,它首先检
查能够加载ObjectName
类,以此判断兼容包是否安装。如果没有安装,则向标准
输出打印一条错误信息:
This release of Apache Tomcat
was packaged to run on J2SE 5.0 or later. It can be run on earlier JVMs
by downloading and installing a compatibility package from the Apache
Tomcat binary download page.
这
条信息也就是第一段代码中JMX_ERROR_MESSAGE
变量的值。下面是Bootstrap
类声明该变量的代码:
private static final String JMX_ERROR_MESSAGE =
"This release of Apache Tomcat was packaged to run on J2SE 5.0 \n"
+ "or later. It can be run on earlier JVMs by downloading and \n"
+ "installing a compatibility package from the Apache Tomcat \n"
+ "binary download page.";
那为什么Tomcat
6中移除了第一段代码,不检查兼容包是否安装了呢?原因很简单,Tomcat 6的设计目标并不包括J2SE 1.4及之前版本。
OK
,看完了第一段,我们进入正题,看看第二段代码。
第二阶段
if (daemon == null) {
daemon = new Bootstrap();
try {
daemon.init();
} catch (Throwable t) {
t.printStackTrace();
return;
}
}
可见,这段代码的主要逻辑在Bootstrap
的init
方法。该方法的工作包括:
- 设
置Catalina
(Tomcat Servlet
容器的代号)的路径:CATALINA_HOME
和CATALINA_BASE
- 初始化Tomcat
的类加载器体系
- 创建org.apache.catalina.startup.Catalina
对
象(启动阶段剩余的工作由Catalina类
完成)
为了
节省篇幅,init
方法的代码另文表述
。下面我们看看第三段代码。
第三阶段
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);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t) {
t.printStackTrace();
}
容
易看出,这段代码的主要逻辑就是根据不同的启动参数,执行不同的工作。可以接受的启动参数包括4
种:startd stopd start stop
。
启动参数决定了启动还是停止Tomcat
。如何启动,如何停止,另文表述
。本文问想讨论的问题是:除了start
和stop
,为什么
还有startd
和stopd
?
它们有什么区别呢?
启动参数的区别
我们先看看start
和startd
。处理start
的
代码比startd
仅多了一行:
daemon.setAwait(true);
这行代码执行后,主线程(即main
函数所在的线程)在Tomcat
启
动过程结束时并不会退出,而是监听SHUTDOWN
端口(默认端口是8005
)。该端口如果接收SHUTDOWN
命
令,就停止Tomcat
;如果收到的是其他命令,则忽略,继续监听。这样,我
们就可以在Tomcat
进程之外通过网络停止Tomcat
。
如果以startd
参
数启动Tomcat
,主线程会在启动结束时退出,只剩下主线程创建的其他线程
(HTTP
监听线程、HTTP
请求线程、Tomcat
后台线程等)。
这样,我们并不能通过网络停止Tomcat
。
如果启动参数是stop
,那么将调用Bootstrap类
的stopServer
方法。该方法通过SHUTDOWN
端口向Tomcat
发送SHUTDOWN
命
令,从而停止Tomcat
。shutdown.bat
就是通过这种方式关闭Tomcat
,
它最终执行的命令是:
java [options]
org.apache.catalina.startup.Bootstrap stop
如果启动参数是stopd,那么
Bootstrap将直接调用Catalina的stop方法,直接停止Tomcat。
综上所述,以start
启动,就以stop
停
止;以startd
启动,就以stopd
停
止。
如果将Tomcat
作为独立的进程运行,那么应该使用start
和stop
,这样
我们就可以通过网络停止Tomcat
。
如果将Tomcat
以嵌入到应用进程的方式运行(例如Eclipse
中运行Tomcat
),
那么应该使用startd
和stopd
。
这样,宿主程序通过普通的方法调用,来启动和停止Tomcat
。
一个Bug
关于这4
个启动参数的讨论,可以参见Bug
47881
。这个Bug
的本意是要指出第三段代码的一个问题
,不过恰好讨论了各种启动参数的区别。
至于这个Bug
,也比较明显:
-
args[0] = "start";
应该是 args[args.length - 1
] = "start";
-
args[0] = "stop";
应该是 args[args.length - 1
] = "stop";
这
个Bug
已经在Tomcat
6
中解决了。
Tomcat 7中引入的configtest启动参数
在Tomcat 7中,新增了configtest启动参数。
public static void main(String args[]) {
// 省略部分代码
if (command.equals("startd")) {
args[args.length - 1] = "start";
daemon.load(args);
daemon.start();
// 省略部分代码
} else if (command.equals("configtest")) {
daemon.load(args);
if (null==daemon.getServer()) {
System.exit(1);
}
System.exit(0);
} else {
// 省略部分代码
}
顾名思义,configtest是为了检测配置参数是否正确,配置参数的主要来源就是conf/server.xml。
从代码可以看出,configtest启动参数就是把load方法给执行了一遍,然后无条件退出。load方法的代码,另文表述
。这里只要知道,load的主要工作之一就是解析conf/server.xml,从而起到检测配置参数是否正确的作用。
configtest通过exit status来返回检测结果。1表示检测到错误,0表示检测结果正确。如果load方法执行成功,就会创建server实例,通过daemon.getServer方法返回;反之,如果配置参数不正确,load方法执行失败,那么就不创建server实例,deamon.getServer方法就返回null。
分享到:
相关推荐
tomcat一直在使用的服务器,使用的支持servlet2.4 jsp2.0
apache-tomcat-5.5.26 免安装版的,加压就可以用了。
apache-tomcat-5.5.26+apache-tomcat-5.5.26-admin.zip
Apache tomcat 5.5.26_src.zip
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,安装版只需要解压后安装,有图形化的管理界面。
RHEL5 +Apache2.2.6+Tomcat5.5.26整合
手把手教你使用jk插件配置Tomcat5.5.26与Apache2.2.9,压缩包中附带Apache2.2.9的安装文件、源代码、jk插件和连接的教程
apache-tomcat-5.5.26,以及apache-tomcat-5.5.26的API文档
Tomcat服务器是一个免费的开放源代码的Web应用服务器
用于解决使用 Tomcat 5.5.26 Administration Tool 的 Delete Existing Hosts 功能时发生 HTTP Status 500 错误,详见 http://blog.csdn.net/LaoBai_2006/archive/2008/08/28/2844042.aspx。 md5: f8ad905990a96f...
打开D:\apache-tomcat-5.5.26\conf下的tomcat-users.xml,添加下面一句: xml 代码 roles="admin,manager"/> 启动tomcat,然后打开IE:http://localhost:8080,点击Tomcat Administration即可进入Tomcat server ...
apache-tomcat-5.5.26Windows Service Installer.EXE ,直接安装并运行即可
打开D:\apache-tomcat-5.5.25\conf下的tomcat-users.xml,添加下面一句: xml 代码 roles="admin,manager"/> 启动tomcat,然后打开IE:http://localhost:8080,点击Tomcat Administration即可进入Tomcat server ...
这是小型的服务器,可以用于个人学习Web开发中用的服务器,小巧方便
博文链接:https://hongan.iteye.com/blog/244845