Tomcat 之 Bootstrap

来源:互联网 发布:大数据的益处 编辑:程序博客网 时间:2024/05/16 04:17

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, 这个类里面最主要的接口如下:

 

Java代码 复制代码 收藏代码
  1. public static ClassLoader createClassLoader(File unpacked[], File packed[], final ClassLoader parent)   
  2.   
  3. public static ClassLoader createClassLoader(List<Repository> repositories, final ClassLoader parent)  
 

通过传入URL列表,以及父加载机制,ClassLoaderFactory产生一个StandardClassLoader的实例。StandardClassLoader类继承于URLClassLoader,并实现了一个空的MBean接口StandardClassLoaderMBean,这样就保证了所有的ClassLoader的实例都可以被JMX来维护。

 

StandardClassLoader的代码如下:

 

Java代码 复制代码 收藏代码
  1. public class StandardClassLoader   
  2.     extends URLClassLoader   
  3.     implements StandardClassLoaderMBean {   
  4.   
  5.     public StandardClassLoader(URL repositories[]) {   
  6.         super(repositories);   
  7.     }   
  8.   
  9.     public StandardClassLoader(URL repositories[], ClassLoader parent) {   
  10.         super(repositories, parent);   
  11.     }   
  12.   
  13. }   
  14.   
  15.   
  16. public interface StandardClassLoaderMBean {   
  17.     // Marker interface   
  18. }  

 

将ClassLoader放入JMX的代码:

 

Java代码 复制代码 收藏代码
  1. // Retrieving MBean server   
  2. MBeanServer mBeanServer = null;   
  3. if (MBeanServerFactory.findMBeanServer(null).size() > 0) {   
  4.     mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);   
  5. else {   
  6.     mBeanServer = ManagementFactory.getPlatformMBeanServer();   
  7. }   
  8.   
  9. // Register the server classloader   
  10. ObjectName objectName =   
  11.     new ObjectName("Catalina:type=ServerClassLoader,name=" + name);   
  12. mBeanServer.registerMBean(classLoader, objectName);  
 

 

 

Catalina调用

Bootstrap类对于所有Catalina方法的调用都是通过反射机制来实现的。采用这种方式的好处就是,将两者有机的分离开来,为将来的扩展提供便利。

原创粉丝点击