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) {
;
} }

tomcat源码分析(一)的更多相关文章

  1. tomcat源码分析(三)一次http请求的旅行-从Socket说起

    p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...

  2. [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat

    概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...

  3. Tomcat源码分析

    前言: 本文是我阅读了TOMCAT源码后的一些心得. 主要是讲解TOMCAT的系统框架, 以及启动流程.若有错漏之处,敬请批评指教! 建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, ...

  4. Tomcat源码分析之—具体启动流程分析

    从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息 ...

  5. Tomcat源码分析--转

    一.架构 下面谈谈我对Tomcat架构的理解 总体架构: 1.面向组件架构 2.基于JMX 3.事件侦听 1)面向组件架构 tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成 ...

  6. tomcat 源码分析

    Tomcat源码分析——Session管理分析(下)    Tomcat源码分析——Session管理分析(上)     Tomcat源码分析——请求原理分析(下)     Tomcat源码分析——请 ...

  7. Tomcat源码分析——Session管理分析(下)

    前言 在<TOMCAT源码分析——SESSION管理分析(上)>一文中我介绍了Session.Session管理器,还以StandardManager为例介绍了Session管理器的初始化 ...

  8. Tomcat源码分析——Session管理分析(上)

    前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对 ...

  9. Tomcat源码分析——请求原理分析(下)

    前言 本文继续讲解TOMCAT的请求原理分析,建议朋友们阅读本文时首先阅读过<TOMCAT源码分析——请求原理分析(上)>和<TOMCAT源码分析——请求原理分析(中)>.在& ...

  10. Tomcat源码分析——请求原理分析(中)

    前言 在<TOMCAT源码分析——请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT源码分析——请求原 ...

随机推荐

  1. AngularJS中如何对Controller与Service进行分层设计与编码

    初学者的Controller 在我们当接触NG后,如需要通过访问远程的API获取一系列的数据进行显示,通常我的Controller代码会写成下面的样子: angular.module('demo') ...

  2. iOS 9界面适配利器:详解Xcode 7的新特性UIStackView

    升级Xcode7后老项目storyBoard出现问题了,一看时新特性搞的鬼.具体 详见:http://www.csdn.net/article/2015-08-04/2825372

  3. RF环境安装-mac-osx10.10-基础环境-安装指南

    一.适用环境: mac系列,osx10.10,自带Python 二.简要步骤: 1. 安装pip,mac自带Python环境,所以我们改成安装pip 2. 安装wxPython,此处我下载的版本是wx ...

  4. Spring Security(17)——基于方法的权限控制

    目录 1.1     intercept-methods定义方法权限控制 1.2     使用pointcut定义方法权限控制 1.3     使用注解定义方法权限控制 1.3.1    JSR-25 ...

  5. UML(Unified Modeling Language)同一建模语言

    wiki定义: UML is a general-purpose, developmental, modeling language in the field of software engineer ...

  6. ubuntu搭建git服务器

    1.准备两台ubuntu虚拟机,其中一个作为server,另一个作为client.检查是否安装ssh,如果没有安装:sudo apt-get install openssh-server, 然后在se ...

  7. extjs 6.2 helloworld

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. 使用SLT工具从SAP导入数据到SAP HANA

    在配置完备的情况下,SLT工具的Replicate 工作是在SAP HANA Data Provisioning中完成的 1. Log on to the SAP HANA Studio 2. Cal ...

  9. 关于去除input type='file'改变组件的默认样式换成自己需要的样式的解决方案

    在工作中时常会遇到如需要上传功能的按钮,而不像需要系统默认的样式时候,可以采取以下的解决方案: <img onclick="getElementById('file').click() ...

  10. intellig idea 快捷键

    可以在设置中更改为 eclipse 风格的快捷键. 默认 按住 ctlr + 左键,会调整到对应的声明处, 如果有实现类,eclipse中给予了选择. 在idea 中如果想直接调整到实现类,那么采用快 ...