`

tomcat启动类org.apache.catalina.startup.Bootstrap(转自CSDN)

阅读更多


org.apache.catalina.startup.Bootstrap
第一步自然从main函数开始,我们可以从中看出bootstrap的初始化过程 

main函数
首先是调用init方法 ,然后根据main的参数,比如start、startd、stop、stopd等等,启动或停止服务器 
ps:start和startd的区别,感觉像是前者用于重新启动 

init方法 
设置系统属性:setCatalinaHome和setCatalinaBase,都是利用System.setProperty方法来实现。user.dir属性指向一个目录,catalina.home属性指向user.dir目录下的bootstrap.jar文件,该文件不存在则指向user.dir本身。catalina.base和catalina.home一样 

初始化classloader 
创建了三个classloader:common,server,shared ,以server为例,创建过程是: 

查找server.loader系统变量,其中包含了以”,“分隔的文件路径(可能是URL、JAR、目录),称为repository。对repository做一些处理后(主要是替换其中的其他环境变量名,以得到完整的绝对路径),利用同一个包里面的另一个类ClassLoaderFactory,来真正产生classloader 。最后将生成的classloader作为mbean保存 

Thread.currentThread().setContextClassLoader(catalinaLoader) 把生成的catalinaLoader作为当前线程上下文的classloader 

利用反射机制,正式载入org.apache.catalina.startup.Catalina类,创建类的实例,并调用该类的setParentClassLoader方法。最后,将该实例赋值给Bootstrap类的catalinaDaemon对象(这个对象类型是Object),完成初始化 

回到main函数 
假设命令参数为start,则依次调用bootstrap的setAwait、load、start方法,这三个方法原理都一样,都是通过反射,实际调用刚才初始化生成的catalinaDaemon的同名方法 

例:start方法中的反射代码

Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null); 
method.invoke(catalinaDaemon, (Object [])null);

Bootstrap类剩下的几个方法:stop、stopServer,都是和start、load一样,通过反射调用catalinaDaemon的同名方法(其实就是org.apache.catalina.startup.Catalina类) 

总结: 
1.反射的大量使用 

无论是classloader,还是具体的某个类,都是通过反射实现初始化和方法调用的。思路是:配置文件->系统属性->解析属性字符串->得到类路径->反射,得到类->方法调用 

这样可以使服务器的实现类很容易被替换,降低耦合性,减少将来代码的改动,的确是一种优秀的设计模式思想 

启动类的配置文件比较简单,都是简单的“键-值”,所以直接用了StringToken解析字符串。后面的代码牵涉到xml配置文件时,必定会换成xml解析器。但总体思路应该类似 

2.JMX的使用 

Bootstrap的JMX用得很少,仅仅对类装载器进行mbean注册,相信后面会有更多JMX的身影

 

org.apache.catalina.startup.ClassLoaderFactory
顾名思义,是tomcat专门用来产生classloader的工厂类 

包括三个重载方法createClassLoader,内容都大同小异,无非是根据传入的类路径参数,产生一个相应的类装载器 

tomcat的类路径分为:包含class文件的目录、jar文件、包含jar的目录和URL 

以Bootstrap类用到的createClassLoader方法为例 

参数为:(String locations[],Integer types[], ClassLoader parent) 
locations即为类路径的字符串表示,types为对应的类路径的类型,这两个数组的长度肯定是相同的,parant即为父classloader 

方法的处理逻辑很简单,即根据每个location的类型,对location字符串做处理,如取得绝对路径、遍历目录、判断是不是jar文件等等 

从代码可以看到,ClassLoaderFactory产生的classloader其实都是org.apache.catalina.loader.StandardClassLoader,这个类装载器留待以后研究

org.apache.catalina.startup.Catalina
Bootstrap中,是通过start方法启动Catalina的 

Catalina中包含一个server实例,对应server.xml中的server元素。如果server实现了Lifecycle,start首先将server实例作为生命周期对象进行启动。然后,在JDK的Runtime中注册一个Shutdownhook。最后,如果指定了await参数,则让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(); 
            } 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(); 
        } 

    }

Shutdownhook是一个Thread对象,用于给JVM在收到停止命令时(例如Ctrl C),运行这些Thread执行收尾工作,具体用法可以参考JAVA文档 

CatalinaShutdownHook在这里就是执行Catalina.stop方法,所以在Catalina.stop方法里面,会手动删除Runtime中的CatalinaShutdownHook,以防止调用两次stop,如下:

// Remove the ShutdownHook first so that server.stop() 
            // doesn't get invoked twice 
            if (useShutdownHook) { 
                Runtime.getRuntime().removeShutdownHook(shutdownHook); 
            }

 

Catalina也有个main函数,不过里头调用的方法都是已废弃的,估计是遗留代码

main函数主要是对命令行参数进行解析,比如可以取代默认的server.xml路径,其余工作主要交给load和start方法 

load方法 
按以下顺序读取配置文件server.xml,通过Digester类进行解析 
1.configFile字段指明的配置文件“conf/server.xml” 
2.Catalina的类装载器的getResource方法(具体原理不清楚,似乎很神奇。和装载类的机制一样,propagate方式,父装载器优先) 
3.最后是从内置的catalina.jar的server-embed.xml读入配置 

一旦读取成功,则后面的不读取,优先级依次降低 
load方法最后进行配置和server的初始化,调用server.initialize方法 

其中,Digester类似乎很神奇很强大,可以根据一定的规则,对一个xml源文件进行解析,然后执行相应的动作,留待以后研究。这里有一篇文章可以参考

http://software.ccidnet.com/pub/article/c322_a31671_p2.html 

 

stop方法

// Shut down the server 
        if (server instanceof Lifecycle) { 
            try { 
               ((Lifecycle) server).stop(); 
            } catch (LifecycleException e) { 
                log.error("Catalina.stop", e); 
            } 
        }

stopserver方法 
比起stop方法要复杂得多,不是简单地调用server.stop,而是通过创建一个Digester,根据配置文件的定义进行动作;然后,以非常“原始”的方法:建立到server的socket连接,以字节流的方式,一个个字符地发送tomcat的“SHUTDOWN”指令,如下:

// Stop the existing server 
       try { 
           String hostAddress = InetAddress.getByName("localhost").getHostAddress(); 
           Socket socket = new Socket(hostAddress, server.getPort()); 
           OutputStream stream = socket.getOutputStream(); 
           String shutdown = server.getShutdown(); 
           for (int i = 0; i < shutdown.length(); i++) 
               stream.write(shutdown.charAt(i)); 
           stream.flush(); 
           stream.close(); 
           socket.close(); 
       } catch (IOException e) { 
           log.error("Catalina.stop: ", e); 
           System.exit(1); 
       }

 

补充
在看完StandardServer后,回到Catalina,现在对于Catalina的stop和stopServer方法的区别又多了一些理解。

关于StandardServer的笔记:

Catalina的stop方法,其实是调用StandardServer.stop,进而停止StandardServer内部的各个Service,是名副其实的真正“停止”服务器 

而stopServer方法,其实是构造一个socket连接到StandardServer的await方法打开的端口上,并发送SHUTDOWN命令。如前面所述,await只是起到阻塞作用,接受到SHUTDOWN命令后则await结束阻塞,并返回。具体要做哪些操作,还得由调用await的代码来决定。 

现在先姑且认为,Catalina的stop方法是单纯的、Catalinal自己定义的一个停止服务器的函数,里面的实现都是封装在Catalina内部的,完成的工作就是停止服务器的socket和相关的Service服务,外人无法改动。 

假如有第三方希望在停止server之前做点别的事情(比如释放特定的资源、或者通知其他组件),那么可以利用stopServer方法,待到await返回后,先完成自己要做的事情,最后再回头调用Catalina.stop(),完成最终的“停止” 。

通过这样的设计,tomcat给了外部代码,或者说基于tomcat的二次开发人员很大的灵活性,不必拘泥于tomcat本身的实现,也有利于tomcat自身的功能扩展。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wangchengsi/archive/2008/09/20/2966850.aspx


2
2
分享到:
评论

相关推荐

    org.apache.catalina.connector.ClientAbortException和TOMCAT的日志配置

    问题1:TOMCAT下载文件出错:org.apache.catalina.connector.ClientAbortException. 问题2:TOMCAT记录接收数据大小、发送数据大小和请求处理时间

    org.apache.catalina.core.AprLifecycleListener

    org.apache.catalina.core.AprLifecycleListener myeclipse tomcat 無法啟動 用這個文件

    apache-tomcat-8.5.78 源码 maven 版本

    apache-tomcat-8.5.78 源码 maven 版本,配置都已经搞定,开箱即用。是学习tomcat的不二之选。启动类 org.apache.catalina.startup.Bootstrap

    tomcat启动的问题--apr

    2010-8-11 18:24:13 org.apache.catalina.core.AprLifecycleListener lifecycleEvent 信息: The Apache Tomcat Native library which allows optimal performance in production environments was not found on the ...

    java基础知识,基础知识

    3月 17, 2019 10:51:41 上午 org.apache.catalina.startup.VersionLoggerListener log 信息: Server version: Apache Tomcat/7.0.78 3月 17, 2019 10:51:41 上午 org.apache.catalina.startup.VersionLoggerListener...

    com.springsource.org.apache.catalina-6.0.16.jar

    jar包,官方版本,自测可用

    apache-tomcat-8.5.100.tar.gz

    - 启动与停止:通过bin目录下的startup.sh或startup.bat启动Tomcat,使用shutdown.sh或shutdown.bat停止。 2. 使用Apache Tomcat托管Web应用: - 将WAR文件放入webapps目录下,Tomcat会自动解压并部署应用。 - ...

    apache-tomcat-7.0.69.zip

    apache-tomcat软件,windows-64版本 日志可查看catalina.out,如下: at org.springframework.web.servlet.mvc.method.annotation... at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)

    windows下tomcat的catalina.out按天自动分割

    完成以上步骤后,每次Tomcat启动或重启时,新的日志文件都会被创建并以日期命名。你可以检查`logs`目录来确认是否已经正确地实现了日志文件的自动分割。 #### 五、注意事项 - 在进行任何配置修改前,务必先备份原始...

    apache-tomcat-8.5.64.tar.gz

    Tomcat启动时会自动检测并部署这些应用。 6. **配置Tomcat** Tomcat的配置主要在`$CATALINA_HOME/conf`目录下的文件中进行,例如`server.xml`定义了服务器配置,包括端口、线程池等。`context.xml`则用于配置全局...

    最新版linux apache-tomcat-8.5.59.tar.gz

    4. **启动Tomcat**:使用`startup.sh`脚本启动Tomcat服务: ``` /opt/tomcat/bin/startup.sh ``` 5. **检查状态**:访问`http://your_server_ip:8080`以确认Tomcat已成功启动并正在运行。如果一切正常,你应该能...

    最新版linux apache-tomcat-9.0.46.tar.gz

    另外,可以通过调整`catalina.sh`或`catalina.bat`中的JVM参数来优化内存分配和垃圾回收,以适应你的特定需求。 9. **部署应用**:将`.war`文件复制到`$CATALINA_HOME/webapps`目录下,Tomcat会自动解压并启动应用...

    apache-tomcat-8.5.75.tar.gz

    在解压后的目录中,`bin` 目录包含了启动和停止Tomcat的脚本,如 `catalina.sh`(在Linux环境下)和 `startup.bat`(在Windows环境下)。`conf` 目录则包含了一系列配置文件,如 `server.xml`(定义服务器的全局配置...

    tomcat服务器跨域需要的CorsFilter jar包文件

    1. **下载CorsFilter**:根据描述,你需要的文件是"tomcat跨域jar文包件",这个文件通常包含`org.apache.catalina.filters.CorsFilter`类,这是Tomcat自带的CORS过滤器实现。你可以从Apache Tomcat的官方网站或者第...

    apache-tomcat-8.5.63.zip

    另外,监控和日志记录也是保持服务器健康的关键,可以利用`catalina.out`和`logs`目录下的其他日志文件进行问题排查。 总的来说,Apache Tomcat 8.5.63是Java Web应用的强大服务器,适用于各种规模的项目。了解其...

    apache-tomcat-8.5.27.tar.gz

    4. **设置权限**:确保Tomcat启动用户对Tomcat目录有适当的读写权限。 5. **启动和管理**:使用`bin/startup.sh`启动Tomcat,`bin/shutdown.sh`关闭Tomcat。还可以使用`bin/catalina.sh`脚本进行其他管理操作。 6....

    最新版linux apache-tomcat-9.0.52.tar.gz

    - 启动Tomcat:`/opt/apache-tomcat-9.0.52/bin/startup.sh` 5. **配置与管理**: - 配置Tomcat可以通过修改`conf/server.xml`文件,比如设置端口号、调整内存分配等。 - 管理Web应用,将`.war`文件放入`webapps...

    最新版linux apache-tomcat-9.0.37.tar.gz

    5. **启动、停止和管理**:Apache Tomcat提供了一系列的脚本用于管理服务,如`bin/startup.sh`用于启动Tomcat,`bin/shutdown.sh`用于关闭Tomcat。这些脚本需要使用`sudo`权限执行。 6. **配置**:Tomcat的配置文件...

    apache-tomcat-7.0.108.tar.gz

    Apache Tomcat是一个开源的Java Servlet容器,主要用于实现JavaServer Pages (JSP)、Java Servlet以及Java EE的Web应用程序。在本例中,我们讨论的是Apache Tomcat 7.0.108版本的tar.gz压缩文件。这个版本是Tomcat 7...

    最新版linux apache-tomcat-8.5.58.tar.gz

    8. **日志和监控**:Tomcat的日志文件位于`logs`目录下,包括`catalina.out`、`host-manager.out`等,这些可以帮助你监控和调试Tomcat的运行状态。 9. **安全考虑**:为了生产环境的安全,需要配置防火墙规则,只...

Global site tag (gtag.js) - Google Analytics