Tomcat 源码学习 之 Bootstrap
类名
Bootstrap
继承关系
无
关联类
Catalina
ClassLoaderFactory
MBeanServer
实现功能
创建Tomcat的classLoader机制
代理Catalina方法调用
初始化全局变量CATALINA_HOME_PROP 和 CATALINA_BASE_PROP
分析
Tomcat启动
Tomcat中共有两个类用于Server的启动,Bootstrap和Catalina。作为Bootstrap的主要工作,是代理Catalina内部方法的调用,其本身并不执行任何Server的启动/关闭操作。可以说,Bootstrap和Catalina做了许多重复的工作。初次看代码的读者,都会有这样的困惑:为什么要把Server启动分到两个类里面来做呢?
这么做的目的主要有两个:
1. 将Catalina及其相关的类加载脱离System ClassLoader。
2. 支持多种Tomcat启动方式。
作为Web Server,Tomcat需要采用和应用程序不同的类加载方式,并确保不同权限的类在内存中有效的隔离。关于Tomcat的类加载机制,我们等下会提到。
同时,通过这种分离,可以确保Tomcat支持多种启动方式,包括standalone,多实例以及嵌入式的方式。
全局变量
Bootstrap类里包含两个很重要的全局变量:CATALINA_HOME_PROP 和 CATALINA_BASE_PROP。当我们通过正常的启动方式启动Tomcat时,这两个变量所指向的是同一个URL:${TOMCAT_HOME}。
那我们为什么需要两个变量来存储同一个值呢?这是因为当我们同时启动多个Tomcat实例(在不同端口上)时,不同实例的CATALINA_BASE_PROP将会指向不同的URL。
基本上来说,CATALINA_HOME_PROP指向公用信息的位置,即bin和lib的父目,而 CATALINA_BASE_PROP指向每个Tomcat目录私有信息的位置,即conf、logs、temp、webapps和work的父目录。
由于我们运行单个实例时,两者是相同URL,所以变量值也相同。而当我们运行多个Tomcat实例时,两者的不同就显现出来了。
类加载机制
Bootstrap类中定义了三个不同的ClassLoader: commonLoader,catalinaLoader 和 sharedLoader。并通过构造这样一个ClassLoader树,以保证模块的类库的私有性:
+---------------------------------------+
| Bootstrap
| |
| System
| |
| Common
| / \
| Catalina Shared
| / \
| WebApp1 WebApp2
+---------------------------------------+
- Bootstrap
- 载入JVM自带的类和$JAVA_HOME/jre/lib/ext/*.jar
- System
- 载入$CLASSPATH/*.class
- Common
- 载入$CATALINA_HOME/common/...,它们对TOMCAT和所有的WEB APP都可见
- Catalina
- 载入$CATALINA_HOME/server/...,它们仅对TOMCAT可见,对所有的WEB APP都不可见
- Shared
- 载入$CATALINA_HOME/shared/...,它们仅对所有WEB APP可见,对TOMCAT不可见
- WebApp
- 载入ContextBase?/WEB-INF/...,它们仅对该WEB APP可见
最终,Tomcat会将这些类加载器全部用JMX加载并管理。
Bootstrap利用ClassLoaderFactory来创建ClassLoader, 这个类里面最主要的接口如下:
public static ClassLoader createClassLoader(File unpacked[], File packed[], final ClassLoader parent)
public static ClassLoader createClassLoader(List<Repository> repositories, final ClassLoader parent)
通过传入URL列表,以及父加载机制,ClassLoaderFactory产生一个StandardClassLoader的实例。StandardClassLoader类继承于URLClassLoader,并实现了一个空的MBean接口StandardClassLoaderMBean,这样就保证了所有的ClassLoader的实例都可以被JMX来维护。
StandardClassLoader的代码如下:
public class StandardClassLoader
extends URLClassLoader
implements StandardClassLoaderMBean {
public StandardClassLoader(URL repositories[]) {
super(repositories);
}
public StandardClassLoader(URL repositories[], ClassLoader parent) {
super(repositories, parent);
}
}
public interface StandardClassLoaderMBean {
// Marker interface
}
将ClassLoader放入JMX的代码:
// Retrieving MBean server
MBeanServer mBeanServer = null;
if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
} else {
mBeanServer = ManagementFactory.getPlatformMBeanServer();
}
// Register the server classloader
ObjectName objectName =
new ObjectName("Catalina:type=ServerClassLoader,name=" + name);
mBeanServer.registerMBean(classLoader, objectName);
Catalina调用
Bootstrap类对于所有Catalina方法的调用都是通过反射机制来实现的。采用这种方式的好处就是,将两者有机的分离开来,为将来的扩展提供便利。
页:
[1]