最近在看Tomcat的源码,下面用博客记下看源码的一些心得。
Tomcat是从org.apache.catalina.startup.Bootstrap#main()开始启动. 大致分为三个步骤,即init、load和start。代码如下:
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(); ★1
} 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); ★2
// 反射调用Catalina的start方法
daemon.start(); ★3
} else if (command.equals("stop")) {
daemon.stopServer(args);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
从以上可以很清楚的看出tomcat是通过参数的不同进行相应的命令调用。
★1 启动、初始化(加载类)
启动之前要进行相应的init()初始化,进行相应的环境设置以及包的加,以下是init()方法。(org.apache.catalina.startup.Bootstrap.init())
public void init()
throws Exception
{
setCatalinaHome();//设置Catalina安装目录
setCatalinaBase();//设置Catalina工作目录
initClassLoaders();//加载jar包
// 将classload设置进线程,以便我们使用时进行调用
Thread.currentThread().
setContextClassLoader(catalinaLoader);
SecurityClassLoad.securityClassLoad(catalinaLoader);
// 加载启动类和调用它的process方法
if (log.isDebugEnabled())
log.debug("Loading startup class");
Class startupClass =
catalinaLoader.loadClass
("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();
// 设置共享扩张类加载器
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);
catalinaDaemon = startupInstance;
}
在加载jar的时候,需要初始化classloader,代码如下:(org.apache.catalina.startup.Bootstrap)
private void initClassLoaders() {
try {
commonLoader = createClassLoader("common", null);
catalinaLoader= createClassLoader("server", commonLoader);
sharedLoader = createClassLoader("shared", commonLoader);
} catch (Throwable t) {
log.error("Class loader creation threw exception", t);
System.exit(1);
}
}
tomcat中的加载方式是:
|-------commonLoader (common)-> System Loader
|-------sharedLoader (shared)-> commonLoader -> System Loader
|-------catalinaLoader(server) -> commonLoader -> System Loader
Common是公共类加载器,负责加载tomcat内部和web应用程序可以看到的类(%CATALINA_HOME%/bin/common下的jar文件),Catalina负责加载的是tomcat内部使用的类(%CATALINA_HOME%/server下的jar文件),这些类对web应用程序不可见。Shared负责加载的是web应用程序之间共享的类(%CATALINA_BASE%/shared下的jar文件),这些类对于tomcat内部是不可见的。如果%CATALINA_HOME%/conf/catalina.Properties中没有指定Common的搜索路径,则用当前的类的类加载器即系统类加载器作为Common。
★2 装载相应的资源
下面主要讲解tomcat的load()方法。下图是Catalina.load方法的时序图。
(1) 从上面的时序图可以看出首先调用Catalina类的load()方法,具体代码如下:
(org.apache.catalina.startup.Catalina)。
public void load() {
initDirs();
// Before digester - it may be needed
initNaming();
// Create and execute our Digester
Digester digester = createStartDigester();
try {
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource); //对server.xml进行解析
inputStream.close();
}
......
// Start the new server
if (server instanceof Lifecycle) {
try {
server.initialize(); //server初始化工作
} catch (LifecycleException e) {
log.error("Catalina.start", e);
}
}
long t2 = System.currentTimeMillis();
log.info("Initialization processed in " + (t2 - t1) + " ms");
}
(2) 在上面的load()方法中需要进行server的初始化工作,下图为Catalina.initialize的时序图,从图中可以看出server初始化所完成的工作。
至此,load方法结束,初期化的工作结束,下面开始进入start方法。
★3 容器启动
容器启动时,会调用Catalina.start(),下图为它的时序图。从图中可以看出StandardService的start方法被调用后会分别对Container和Connector进行start方法的调用。
1. Bootstrap调用Catalina的start方法
Catalina.start()方法(org.apache.catalina.startup.Catalina.start())
public void start() {
// 启动server
if (server instanceof Lifecycle) {
try {
((Lifecycle) server).start();
......
}
2. Catalina调用StandardServer的start方法
StandardServer.start() (org.apache.catalina.core.StandardServer.start() )
public void start() throws LifecycleException {
synchronized (services) {
for (int i = 0; i < services.length; i++) {
if (services[i] instanceof Lifecycle)
((Lifecycle) services[i]).start();
}
}
3. StandardServer调用StandardService的start方法
org.apache.catalina.core.StandardService.start() )
public void start() throws LifecycleException {
if (container != null) {
synchronized (container) {
if (container instanceof Lifecycle) {
// standardEngine的启动
((Lifecycle) container).start();
}
}
//两个connector的启动,8080和8009
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++) {
if (connectors[i] instanceof Lifecycle)
((Lifecycle) connectors[i]).start();
}
}
}
以上StandardService.start()方法主要实现了两个功能,standardEngine的启动和connector的启动,下面分别来介绍。
- 大小: 16.4 KB
- 大小: 10.9 KB
- 大小: 15.8 KB
分享到:
相关推荐
tomcat-redis-session-manager源码
开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-...
apache-tomcat-8.5.20.tar.gz源码包和context.xml文件,这套配置是我自己亲测可用的。。另外我用的redis4这个版本。注意:如果你使用的TOMCAT其他版本。例如tomcat6或者7这套JAR包可能不可用,tomcat8.0没有测试。...
Tomcat8亲测可用 tomcat-redis-session-manager的jar包 修改了tomcat-redis-session-manager源码进行的编译生成的jar包
7.0.59版本,直接去关联这个压缩包即可.如果版本不对http://archive.apache.org/dist/tomcat/去官网直接下也可以.
apache-tomcat-6.0.53-src,apache tomcat 6.0.53的源码。 压缩包文件清单: apache-tomcat-6.0.53-src.tar.gz apache-tomcat-6.0.53-src.tar.gz.asc apache-tomcat-6.0.53-src.tar.gz.md5 apache-tomcat-6.0.53-...
apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-...
这个是一个Tomcat源码,喜欢代码分析的课可以参考这个源码进行学习,网上有很多的源码导入方式,可以参考网上的源码导入方式来进行Tomcat源码学习
因tomcat7使用redis共享session,其他的包存在问题,自己编译后处理通过。 该包是在https://github.com/jcoleman/tomcat-redis-session-manager 将源码编译后的包。
apache-tomcat-7.0.90-src源码 apache-tomcat-7.0.90-src源码
MyEclipse导入Tomcat源码.wps文档说明 apache-tomcat-6.0.37-src.zip源码
tomcat8下 tomcat-redis-session-manager , github上有源码,其他版本都有打好的jar包,tomcat 8 下没有,下载源码生成了一个。
apache-tomcat-9.0.14-src 源码 tomcat-9.0.14源码
基于tomcat-redis-session-manager源码进行的编译生成的jar包,压缩包中包含Tomcat7和Tomcat8打好的jar包。
tomcat 源码分析系列文档 http深入分析,tomcat中类的加载,tomcat的启动,tomcat的容器思想,
centos源码安装apache-tomcat-8.0.21
apache-tomcat-7.0.59-src apache-tomcat-7.0.69-src Tomcat 7.0.59,Tomcat 7.0.69 源码
tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码
tomcat-connectors-1.2.32-src.tar.gz 在linux下,进行apache和tomcat整合时要用的源码安装文件
该压缩包含有apache-tomcat-7.0.62-src和apache-tomcat-6.0.39-src的源码。