打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
[源码学习]Tomcat6 源码学习
【tomcat启动类Bootstrap】 
t1.tomcat的人口函数,启动类 
org.apache.catalina.startup. Bootstrap.java   Main函数 

t2.Bootstrap类 
初始化 ClassLoader, 然后利用 Java Reflection 调用 Catalina 类来启动 tomcat server 

【tomcat扩展-日志】 
a1.private static Log log = LogFactory.getLog(Bootstrap.class); 
日志可以定义为private 和static 

a2.只在本类中使用的方法,使用private,降低访问权限,需要的时候,再考虑重构或者提高访问权限public 

a.日志打印前加if(log.isInfoEnabled()) 
如果代码中含有logger.debug(“string”);此类语句,尽管在log4j.xml配置文件中对该类logger的level为 ERROR,但是仍然会产生较大的内存开销,通常是所要输出的string的几十倍甚至上百倍大小,对内存开销非常大。优化方法为:使用logger进行 判断。 


2010-3-30 
【tomcat扩展-classloader】 
a3.如果两个类属于同一个包下,但是由不同的classloader加载,那么他们也不能互访default类型方法,属性 

a4.classloader:与C或C++编写的程序不同,Java程序并不是一个可执行文件,而是由许多独立的类文件组成,每一个文件基本上 对应于一个类。此外,这些类文件并非立即全部都装入内存,而是根据程序需要装入内存。ClassLoader是JVM中将类装入内存的那部分 

a5.定制的ClassLoader应用: 
1.在执行非置信代码之前,自动验证数字签名 
2.使用用户提供的密码透明地解密代码 
3.动态地创建符合用户特定需要的定制化构建类 
4.任何您认为可以生成Java字节码的内容都可以集成到应用程序中 

a6.findClass方法是创建定制的ClassLoader时唯一需要覆盖的方法。 
ClassLoader loadClass方法 
Class c = findLoadedClass(name); 
if (c == null) { 
    try { 
if (parent != null) { 
    c = parent.loadClass(name, false); 
} else { 
    c = findBootstrapClass0(name); 

    } catch (ClassNotFoundException e) { 
        // If still not found, then invoke findClass in order 
        // to find the class. 
        c = findClass(name); 
    } 


a7.ClassLoader(CCL)的任务是确保代码被编译和更新。 
下面描述了它的工作方式:1、当请求一个类时,先查看它是否在磁盘的当前目录或相应的子目录。 
2、如果该类不存在,但源码中有,那么调用Java编译器来生成类文件。 
3、如果该类已存在,检查它是否比源码旧。如果是,调用Java编译器来重新生成类文件。 
4、如果编译失败,或者由于其它原因不能从现有的源码中生成类文件,返回ClassNotFoundException。 
5、如果仍然没有该类,也许它在其它库中,所以调用findSystemClass来寻找该类。 
6、如果还是没有,则返回ClassNotFoundException。 
7、否则,返回该类。 
8、调用findLoadedClass来查看是否存在已装入的类。 
9、如果没有,那么采用那种特殊的神奇方式来获取原始字节。 
10、如果已有原始字节,调用defineClass将它们转换成Class对象。 
11、如果没有原始字节,然后调用findSystemClass查看是否从本地文件系统获取类。 
12、如果resolve参数是true,那么调用resolveClass解析Class对象。 
13、如果还没有类,返回ClassNotFoundException。 
14、否则,将类返回给调用程序。 

【tomcat启动类classloader】 
t3.tomcat自定义了三个类,catalinaLoader commonLoader,sharedLoader 
Common - 载入$CATALINA_HOME/common/...它们对TOMCAT和所有的WEB APP都可见 
Catalina - 载入$CATALINA_HOME/server/..它们仅对TOMCAT可见,对所有的WEB APP都不可见 
Shared-载入$CATALINA_HOME/shared/它们仅对所有WEB APP可见,对TOMCAT不可见(也不必见) 

t4.Bootstrap通过反射初始化Catalina类, 
反射调用Catalina方法setParentClassLoader,传递SharedClassloader 
反射call Catalina方法load 利用server.xml中的配置初始化Service,Server,Engine,Host 
反射call Catalina方法start Start the new server  该server是通过  解析xml文件生成的org.apache.catalina.core.StandardServer类 


【tomcat-xml解析】 
1.Tomcat取了Digester中的interface和几个Rule,并且自己实现了一些 Rule 来解析xml. 
2.tomcat解析xml创建以下几个类 
Server: 
org.apache.catalina.core.StandardServer 
Resources: 
org.apache.catalina.deploy.NamingResources 
Server's Listener:( 监听server事件) 
org.apache.catalina.core.AprLifecycleListener 
org.apache.catalina.core.JasperListener 
org.apache.catalina.mbeans.ServerLifecycleListener 
org.apache.catalina.mbeans.GlobalResourcesLifecycleListener 
Service: 
org.apache.catalina.core.StandardService 
Executor: 
org.apache.catalina.core.StandardThreadExecutor 
Engine: 
org.apache.catalina.core.StandardEngine 
Connector: 
org.apache.catalina.connector.Connector 

【tomcat-流程】 
3.StandardServer启动StandardService,StandardService启动Connector, 
Connector启动Http11Protocol,Http11Protocol启动JIoEndpoint, 
JioEndpoint启动server Socket,listern 8080端口,处理http请求 

4.Http11Processor 
Processes HTTP requests. 
由http11ConnectionHandler调用,Http11ConnectionHandler由JioEndpoint中的Work 调用 

5.A connector passes the request and reponse objects to the Container by calling the Container interface's invoke method 
public void invoke(Request request, Response response) 
        throws IOException, ServletException; 

inside the invoke method ,the container loads the servlet class,call its sevice method ,manage sessions,etc. 

6.Connector 方法initialize中 
// Initializa adapter 
adapter = new CoyoteAdapter(this); 
protocolHandler.setAdapter(adapter); 
adapter通过protocolHandler(Http11Protocol)传给Http11Processor, 
Http11Processor解析,create request和response,通过adapter传送给Container 

7.Tomcat使用Pipeline模式在各层容器间传递请求,将请求通过管道依次通过Engine,Host,Context和 Wrapper。另外,每一个容器   
都可以设置一系列的Valve去对请求进行拦 截,就像管道中的阀一样对请求的行为进行一些干涉。 


2010-3-31 
【tomcat-流程】 
1.tomcat的pipeline/valve是标准的责任链模式,每个级别的容器中pipeline所有的valve都完成动作后会将 request/response传到下一个容器的pipeline中的valve, 
这样一直传递下去直到Wrapper的BaseValve. 
Ps:每个容器的BaseValve会调用下个容器的起始valve 

2.StandardEngine 
属性Pipeline  pipeline = new StandardPipeline(this); 
构造函数里会设置最底层的阀门 
pipeline.setBasic(new StandardEngineValve()); 
如果需要设置新阀门处理需求,只需要调用 pipeline.addValve(Valve valve); 

3.CoyoteAdapter中会执行 
connector.getContainer().getPipeline().getFirst().invoke(request, response); 
该行代码会一层一层调用添加的阀门,处理下去. 

2010-4-1 
【tomcat-流程】 
1.jk插件负责tomcat和其它http容器进行通信 

2.连接器协议AJP/1.3是tomcat用来与其它http容器进行连接的协议 

3.把指定Context的classloader付给当前线程。 
Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader()); 这样request就只看见指定的context下面的classes和jar包,而看不见tomcat本身的类。 

2010-4-7 
【tomcat-socke与worker线程】 
/** 
* Process an incoming TCP/IP connection on the specified socket.  Any 
* exception that occurs during processing must be logged and swallowed. 
* <b>NOTE</b>:  This method is called from our Connector's thread.  We 
* must assign it to our own thread so that multiple simultaneous 
* requests can be handled. 
* @param socket TCP socket to process 
*/ 
synchronized void assign(Socket socket) { 
// Wait for the Processor to get the previous Socket 
while (available) { 
try { 
              wait(); 
       } catch (InterruptedException e) { 
       } 
    } 
    // Store the newly available Socket and notify our thread 
    this.socket = socket; 
    available = true; 
    notifyAll(); 


/** 
* Await a newly assigned Socket from our Connector, or <code>null</code 
* if we are supposed to shut down. 
*/ 
private synchronized Socket await() { 
// Wait for the Connector to provide a new Socket 
while (!available) { 
try { 
wait(); 
} catch (InterruptedException e) { 


    // Notify the Connector that we have received this Socket 
    Socket socket = this.socket; 
    available = false; 
    notifyAll(); 
return (socket); 

连接器线程调用worker类的assign类,worker类的执行线程run方法会调用await方法获取socket,通过 available变量的设置和wait/notify方法来协调彼此的操作。当连接器线程未传输socket,worker类线程就执行wait等待, 
当worker类执行线程在处理忙的时候,连接器线程wait。


一直以来都是用tomcat做web服务器进行开发,很想知道其内部的一些原理和实现(虽然很多人说知道原理又不能当饭吃)。今天跟踪调试了源码的启动程序(关于源码的eclipse的导入以及ant的构建,网上有大把的资料,google一下就ok了),总算知道点大致的启动步骤,有些浅显的领悟分享一下:
org.apache.catalina.startup.Bootstrap作为启动入口,此类的main函数:
1.首先创建一个自身的实例(如果此类的实例变量:private static Bootstrap daemon为空的话);

2.然后调用init()方法,此方法的主要工作就是反射得到org.apache.catalina.startup.Catalina的实例,同时把classLoader通过Catalina的setParentClassLoader方法赋值。

3.接着调用load(args)方法,此方法反射调用Catalina的load(args),根据传递的参数设置部分属性值之后,会接着执行Catalina的load()方法。
在这个无参的方法里通过Digester组件(Jakarta Commons Digester是apache的一个解析处理xml的开源项目,开始我还以为巧合,因为struts的ActionServlet也是使用此组件解析,后来才知道tomcat的一个主力也是struts的创造者之一)解析conf/server.xml等xml文件,初始化一系列的参数。

4.接着Bootstrap的start()方法反射调用Catalina的start()方法,此方法通过调用xml解析处理后得到的server:org.apache.catalina.core.StandardServer的start()方法进入其所拥有的Lifecycle service:org.apache.catalina.core.StandardService的start()方法,接着调用Lifecycle Container:org.apache.catalina.core.StandardEngine的start()方法,初始化一堆东西之后到达旅途的终点,StandardEngine的父类:org.apache.catalina.core.ContainerBase的start(),这个方法是通过自身的threadStart()方法启动了一个容器线程:
thread = new Thread(new ContainerBackgroundProcessor(), threadName);
thread.setDaemon(true);
thread.start();

5.上面的繁文的简化大致是:Bootstrap(init,load,start)--> Catalina(start)--> StandardServer(start)--> StandardService(start)--> StandardEngine(start)--> ContainerBase(start, threadStart)

至此终于看到双击.bat或者执行.sh背后的一点点东西了(我是跟踪的6.0.20的源码,可能之前的版本的有所不同)。



本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
java开发中有关mian函数的一些疑问
[错误]TOMCAT启动报错Socket bind failed等解决方法
Tomcat的类载入器-Tomcat笔记(3)
配置Tomcat使用https协议
Roller4.0.1源码编译安装
Tomcat初始化跟启动详细过程
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服