tomcat的启动从Bootstrap类的main方法开始。

 public static void main(String args[]) {

        //单例
if (daemon == null) {
daemon = new Bootstrap();//实例化Bootstrap对象
try {
//实例化Catalina 并装载3个classloader,设置Catalina的父加载器
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();
} }
/**
* 一些初始化工作 初始化一个守护线程
* Initialize daemon.
*/
public void init()
throws Exception
{ // Set Catalina path 初始化Tomcat的安装路径 home\base
setCatalinaHome();
setCatalinaBase(); initClassLoaders();//初始化变量classloader:catalinaloader、commonloader、sharedloader 三个加载器 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();//得到了Catalina的实例 // 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的setParentClassLoader方法 设置共享扩展类装入器 catalinaDaemon = startupInstance; //赋值给Catalina的成员变量。
}
 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); }

Catalina的load方法。主要是解析conf下的service.xml文件

    public void load() {

        long t1 = System.nanoTime();

        initDirs();//System.setPropertity("catalina.home")和catalina.home  设置系统目录

        // Before digester - it may be needed

        initNaming();//设置propertity  naming

        // Create and execute our Digester
Digester digester = createStartDigester(); InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
try {
file = configFile();//读取con/server.xml的配置文件
inputStream = new FileInputStream(file);
inputSource = new InputSource("file://" + file.getAbsolutePath());
} catch (Exception e) {
;
}
if (inputStream == null) {
try {
inputStream = getClass().getClassLoader()
.getResourceAsStream(getConfigFile());
inputSource = new InputSource
(getClass().getClassLoader()
.getResource(getConfigFile()).toString());
} catch (Exception e) {
;
}
} // This should be included in catalina.jar
// Alternative: don't bother with xml, just create it manually.
if( inputStream==null ) {
try {
inputStream = getClass().getClassLoader()
.getResourceAsStream("server-embed.xml");
inputSource = new InputSource
(getClass().getClassLoader()
.getResource("server-embed.xml").toString());
} catch (Exception e) {
;
}
} if ((inputStream == null) && (file != null)) {
log.warn("Can't load server.xml from " + file.getAbsolutePath());
return;
} try {
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);//解析service.xml配置文件
inputStream.close();
} catch (Exception e) {
log.warn("Catalina.start using "
+ getConfigFile() + ": " , e);
return;
} // Stream redirection
initStreams(); // Start the new server
if (server instanceof Lifecycle) {
try {
server.initialize();
} catch (LifecycleException e) {
log.error("Catalina.start", e);
}
} long t2 = System.nanoTime();
if(log.isInfoEnabled())
log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms"); }

tomcat从Catalina的start方法开启了。

 public void start() {

        if (server == null) {
load();
} long t1 = System.nanoTime(); // Start the new server
if (server instanceof Lifecycle) {
try {
((Lifecycle) server).start();//这里的server是StandardService,在这里启动服务。
} catch (LifecycleException e) {
log.error("Catalina.start: ", e);
}
} long t2 = System.nanoTime();
if(log.isInfoEnabled())
log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms"); try {
// Register shutdown hook
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
} catch (Throwable t) {
// This will fail on JDK 1.2. Ignoring, as Tomcat can run
// fine without the shutdown hook.
} if (await) {
await();
stop();
} }

启动完成后,等待客户端的链接。

 public void await() {

        server.await();

    }

建立Socket,等待客户端的链接

public void await() {
// Negative values - don't wait on port - tomcat is embedded or we just don't like ports
if( port == -2 ) {
// undocumented yet - for embedding apps that are around, alive.
return;
}
if( port==-1 ) {
while( true ) {
try {
Thread.sleep( 10000 );
} catch( InterruptedException ex ) {
}
if( stopAwait ) return;
}
} // Set up a server socket to wait on
ServerSocket serverSocket = null;
try {
serverSocket =
new ServerSocket(port, 1,
InetAddress.getByName("localhost"));//创建了服务端Socket,绑定了localhost/127.0.0.1地址,端口号是8005
} catch (IOException e) {
log.error("StandardServer.await: create[" + port
+ "]: ", e);
System.exit(1);
} // Loop waiting for a connection and a valid command
while (true) {
//循环等待客户端连接
// Wait for the next connection
Socket socket = null;
InputStream stream = null;
try {
socket = serverSocket.accept();//启动完成了,在等待客户端的链接
socket.setSoTimeout(10 * 1000); // Ten seconds
stream = socket.getInputStream();//得到socket的输入流
} catch (AccessControlException ace) {
log.warn("StandardServer.accept security exception: "
+ ace.getMessage(), ace);
continue;
} catch (IOException e) {
log.error("StandardServer.await: accept: ", e);
System.exit(1);
} // Read a set of characters from the socket
StringBuffer command = new StringBuffer();
int expected = 1024; // Cut off to avoid DoS attack
while (expected < shutdown.length()) {
if (random == null)
random = new Random();
expected += (random.nextInt() % 1024);
}
while (expected > 0) {
int ch = -1;
try {
ch = stream.read();//读取流中的数据
} catch (IOException e) {
log.warn("StandardServer.await: read: ", e);
ch = -1;
}
if (ch < 32) // Control character or EOF terminates loop
break;
command.append((char) ch);//将数据添加到stringbuffer中
expected--;
} // Close the socket now that we are done with it
try {
socket.close();
} catch (IOException e) {
;
} // Match against our command string
boolean match = command.toString().equals(shutdown);//判断是否关闭应用
if (match) {
break;
} else
log.warn("StandardServer.await: Invalid command '" +
command.toString() + "' received"); } // Close the server socket and return
try {
serverSocket.close();//退出循环,关闭服务端socket
} catch (IOException e) {
;
} }

最新文章

  1. ztree
  2. SQL递归
  3. 完成端口CreateIoCompletionPort编写高性能的网络模型程序
  4. jsp&amp;servlet学习笔记
  5. PYTHON实现HTTP摘要认证(DIGEST AUTHENTICATION)
  6. 动手实践:在Windows上安装NumPy、Matplotlib、SciPy和IPython
  7. 【转】【教程】office 2013 &amp; visio 2013的激活
  8. 【Xilinx-VDMA模块学习】-01- VDMA IP的GUI配置介绍
  9. SQLite 之 C#版 System.Data.SQLite 使用
  10. JFreeChart与AJAX+JSON+ECharts两种处理方式生成热词统计可视化图表
  11. java 实现递归实现tree
  12. 彻底征服 Spring AOP 之 实战篇
  13. Unity3D中的生命周期函数
  14. SharePoint 2013 workflows stop working (Failed on started.)
  15. Windows下同一台机器上elasticsearch集群的配置以及elasticsearch-head插件的使用
  16. 测试用例Excel模板For Quality Center
  17. opencv——Rect和RotatedRect类详解
  18. C++获取private的变量-偷走private
  19. BZOJ 3190 赛车 | 计算几何
  20. Objective-C代码学习大纲(4)

热门文章

  1. 【android错误】bitmap size exceeds 32bits
  2. 【NOIP2011提高组】选择客栈
  3. Proxy SwitchySharp chrome网络代理【转】
  4. 洛谷-乘积最大-NOIP2000提高组复赛
  5. robotium如何定位控件?
  6. 手动安装VS code 插件
  7. Oracle SQL 关键字
  8. autoconfig操作小结
  9. centos7 安装nodejs,git
  10. token 小记