﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-小小程序员-随笔分类-源码学习</title><link>http://www.blogjava.net/yuoveyu/category/45393.html</link><description>小小程序员</description><language>zh-cn</language><lastBuildDate>Mon, 21 Jun 2010 02:29:15 GMT</lastBuildDate><pubDate>Mon, 21 Jun 2010 02:29:15 GMT</pubDate><ttl>60</ttl><item><title>[源码学习]Tomcat6 源码学习</title><link>http://www.blogjava.net/yuoveyu/archive/2010/06/21/324046.html</link><dc:creator>余坚</dc:creator><author>余坚</author><pubDate>Mon, 21 Jun 2010 02:28:00 GMT</pubDate><guid>http://www.blogjava.net/yuoveyu/archive/2010/06/21/324046.html</guid><wfw:comment>http://www.blogjava.net/yuoveyu/comments/324046.html</wfw:comment><comments>http://www.blogjava.net/yuoveyu/archive/2010/06/21/324046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yuoveyu/comments/commentRss/324046.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yuoveyu/services/trackbacks/324046.html</trackback:ping><description><![CDATA[Tomcat6 源码学习
<br />
2010-3-29
<br />
【tomcat启动类Bootstrap】
<br />
t1.tomcat的人口函数，启动类
<br />
org.apache.catalina.startup. Bootstrap.java&nbsp;&nbsp; Main函数
<br />
<br />
t2.Bootstrap类
<br />
初始化 ClassLoader, 然后利用 Java Reflection 调用 Catalina 类来启动 tomcat server
<br />
<br />
【tomcat扩展-日志】
<br />
a1.private static Log log = LogFactory.getLog(Bootstrap.class);
<br />
日志可以定义为private 和static
<br />
<br />
a2.只在本类中使用的方法,使用private,降低访问权限,需要的时候,再考虑重构或者提高访问权限public
<br />
<br />
a.日志打印前加if(log.isInfoEnabled())
<br />
如果代码中含有logger.debug(&#8220;string&#8221;);此类语句，尽管在log4j.xml配置文件中对该类logger的level为
ERROR，但是仍然会产生较大的内存开销，通常是所要输出的string的几十倍甚至上百倍大小，对内存开销非常大。优化方法为：使用logger进行
判断。
<br />
<br />
<br />
2010-3-30
<br />
【tomcat扩展-classloader】
<br />
a3.如果两个类属于同一个包下，但是由不同的classloader加载，那么他们也不能互访default类型方法,属性
<br />
<br />
a4.classloader:与C或C++编写的程序不同，Java程序并不是一个可执行文件，而是由许多独立的类文件组成，每一个文件基本上
对应于一个类。此外，这些类文件并非立即全部都装入内存，而是根据程序需要装入内存。ClassLoader是JVM中将类装入内存的那部分
<br />
<br />
a5.定制的ClassLoader应用:
<br />
1.在执行非置信代码之前，自动验证数字签名
<br />
2.使用用户提供的密码透明地解密代码
<br />
3.动态地创建符合用户特定需要的定制化构建类
<br />
4.任何您认为可以生成Java字节码的内容都可以集成到应用程序中
<br />
<br />
a6.findClass方法是创建定制的ClassLoader时唯一需要覆盖的方法。
<br />
ClassLoader loadClass方法
<br />
Class c = findLoadedClass(name);
<br />
if (c == null) {
<br />
&nbsp;&nbsp;&nbsp; try {
<br />
if (parent != null) {
<br />
&nbsp;&nbsp;&nbsp; c = parent.loadClass(name, false);
<br />
} else {
<br />
&nbsp;&nbsp;&nbsp; c = findBootstrapClass0(name);
<br />
}
<br />
&nbsp;&nbsp;&nbsp; } catch (ClassNotFoundException e) {
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // If still not found, then invoke findClass in order
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // to find the class.
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c = findClass(name);
<br />
&nbsp;&nbsp;&nbsp; }
<br />
}
<br />
<br />
a7.ClassLoader(CCL)的任务是确保代码被编译和更新。
<br />
下面描述了它的工作方式：1、当请求一个类时，先查看它是否在磁盘的当前目录或相应的子目录。
<br />
2、如果该类不存在，但源码中有，那么调用Java编译器来生成类文件。
<br />
3、如果该类已存在，检查它是否比源码旧。如果是，调用Java编译器来重新生成类文件。
<br />
4、如果编译失败，或者由于其它原因不能从现有的源码中生成类文件，返回ClassNotFoundException。
<br />
5、如果仍然没有该类，也许它在其它库中，所以调用findSystemClass来寻找该类。
<br />
6、如果还是没有，则返回ClassNotFoundException。
<br />
7、否则，返回该类。
<br />
8、调用findLoadedClass来查看是否存在已装入的类。
<br />
9、如果没有，那么采用那种特殊的神奇方式来获取原始字节。
<br />
10、如果已有原始字节，调用defineClass将它们转换成Class对象。
<br />
11、如果没有原始字节，然后调用findSystemClass查看是否从本地文件系统获取类。
<br />
12、如果resolve参数是true，那么调用resolveClass解析Class对象。
<br />
13、如果还没有类，返回ClassNotFoundException。
<br />
14、否则，将类返回给调用程序。
<br />
<br />
【tomcat启动类classloader】
<br />
t3.tomcat自定义了三个类，catalinaLoader commonLoader，sharedLoader
<br />
Common - 载入$CATALINA_HOME/common/...它们对TOMCAT和所有的WEB APP都可见
<br />
Catalina - 载入$CATALINA_HOME/server/..它们仅对TOMCAT可见，对所有的WEB APP都不可见
<br />
Shared-载入$CATALINA_HOME/shared/它们仅对所有WEB APP可见,对TOMCAT不可见（也不必见）
<br />
<br />
t4.Bootstrap通过反射初始化Catalina类，
<br />
反射调用Catalina方法setParentClassLoader，传递SharedClassloader
<br />
反射call Catalina方法load 利用server.xml中的配置初始化Service,Server,Engine,Host
<br />
反射call Catalina方法start Start the new server&nbsp; 该server是通过&nbsp;
解析xml文件生成的org.apache.catalina.core.StandardServer类
<br />
<br />
<br />
【tomcat-xml解析】
<br />
1.Tomcat取了Digester中的interface和几个Rule,并且自己实现了一些 Rule 来解析xml.
<br />
2.tomcat解析xml创建以下几个类
<br />
Server:
<br />
org.apache.catalina.core.StandardServer
<br />
Resources:
<br />
org.apache.catalina.deploy.NamingResources
<br />
Server's Listener:（ 监听server事件）
<br />
org.apache.catalina.core.AprLifecycleListener
<br />
org.apache.catalina.core.JasperListener
<br />
org.apache.catalina.mbeans.ServerLifecycleListener
<br />
org.apache.catalina.mbeans.GlobalResourcesLifecycleListener
<br />
Service:
<br />
org.apache.catalina.core.StandardService
<br />
Executor:
<br />
org.apache.catalina.core.StandardThreadExecutor
<br />
Engine:
<br />
org.apache.catalina.core.StandardEngine
<br />
Connector:
<br />
org.apache.catalina.connector.Connector
<br />
<br />
【tomcat-流程】
<br />
3.StandardServer启动StandardService，StandardService启动Connector，
<br />
Connector启动Http11Protocol，Http11Protocol启动JIoEndpoint，
<br />
JioEndpoint启动server Socket，listern 8080端口,处理http请求
<br />
<br />
4.Http11Processor
<br />
Processes HTTP requests.
<br />
由http11ConnectionHandler调用，Http11ConnectionHandler由JioEndpoint中的Work
调用
<br />
<br />
5.A connector passes the request and reponse objects to the
Container by calling the Container interface's invoke method
<br />
public void invoke(Request request, Response response)
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws IOException, ServletException;
<br />
<br />
inside the invoke method ,the container loads the servlet class,call
its sevice method ,manage sessions,etc.
<br />
<br />
6.Connector 方法initialize中
<br />
// Initializa adapter
<br />
adapter = new CoyoteAdapter(this);
<br />
protocolHandler.setAdapter(adapter);
<br />
adapter通过protocolHandler(Http11Protocol)传给Http11Processor,
<br />
Http11Processor解析，create request和response,通过adapter传送给Container
<br />
<br />
7.Tomcat使用Pipeline模式在各层容器间传递请求，将请求通过管道依次通过Engine，Host，Context和
Wrapper。另外，每一个容器&nbsp;&nbsp;
<br />
都可以设置一系列的Valve去对请求进行拦 截，就像管道中的阀一样对请求的行为进行一些干涉。
<br />
<br />
<br />
2010-3-31
<br />
【tomcat-流程】
<br />
1.tomcat的pipeline/valve是标准的责任链模式,每个级别的容器中pipeline所有的valve都完成动作后会将
request/response传到下一个容器的pipeline中的valve,
<br />
这样一直传递下去直到Wrapper的BaseValve.
<br />
Ps:每个容器的BaseValve会调用下个容器的起始valve
<br />
<br />
2.StandardEngine
<br />
属性Pipeline&nbsp; pipeline = new StandardPipeline(this);
<br />
构造函数里会设置最底层的阀门
<br />
pipeline.setBasic(new StandardEngineValve());
<br />
如果需要设置新阀门处理需求，只需要调用 pipeline.addValve(Valve valve);
<br />
<br />
3.CoyoteAdapter中会执行
<br />
connector.getContainer().getPipeline().getFirst().invoke(request,
response);
<br />
该行代码会一层一层调用添加的阀门,处理下去.
<br />
<br />
2010-4-1
<br />
【tomcat-流程】
<br />
1.jk插件负责tomcat和其它http容器进行通信
<br />
<br />
2.连接器协议AJP/1.3是tomcat用来与其它http容器进行连接的协议
<br />
<br />
3.把指定Context的classloader付给当前线程。
<br />
Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
这样request就只看见指定的context下面的classes和jar包,而看不见tomcat本身的类。
<br />
<br />
2010-4-7
<br />
【tomcat-socke与worker线程】
<br />
/**
<br />
* Process an incoming TCP/IP connection on the specified socket.&nbsp;
Any
<br />
* exception that occurs during processing must be logged and
swallowed.
<br />
* &lt;b&gt;NOTE&lt;/b&gt;:&nbsp; This method is called from our
Connector's thread.&nbsp; We
<br />
* must assign it to our own thread so that multiple simultaneous
<br />
* requests can be handled.
<br />
* @param socket TCP socket to process
<br />
*/
<br />
synchronized void assign(Socket socket) {
<br />
// Wait for the Processor to get the previous Socket
<br />
while (available) {
<br />
try {
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait();
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
<br />
&nbsp;&nbsp;&nbsp; }
<br />
&nbsp;&nbsp;&nbsp; // Store the newly available Socket and notify our thread
<br />
&nbsp;&nbsp;&nbsp; this.socket = socket;
<br />
&nbsp;&nbsp;&nbsp; available = true;
<br />
&nbsp;&nbsp;&nbsp; notifyAll();
<br />
}
<br />
<br />
/**
<br />
* Await a newly assigned Socket from our Connector, or
&lt;code&gt;null&lt;/code
<br />
* if we are supposed to shut down.
<br />
*/
<br />
private synchronized Socket await() {
<br />
// Wait for the Connector to provide a new Socket
<br />
while (!available) {
<br />
try {
<br />
wait();
<br />
} catch (InterruptedException e) {
<br />
}
<br />
}
<br />
&nbsp;&nbsp;&nbsp; // Notify the Connector that we have received this Socket
<br />
&nbsp;&nbsp;&nbsp; Socket socket = this.socket;
<br />
&nbsp;&nbsp;&nbsp; available = false;
<br />
&nbsp;&nbsp;&nbsp; notifyAll();
<br />
return (socket);
<br />
}
<br />
连接器线程调用worker类的assign类，worker类的执行线程run方法会调用await方法获取socket，通过
available变量的设置和wait/notify方法来协调彼此的操作。当连接器线程未传输socket，worker类线程就执行wait等待，
<br />
当worker类执行线程在处理忙的时候，连接器线程wait。
<br />
<img src ="http://www.blogjava.net/yuoveyu/aggbug/324046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yuoveyu/" target="_blank">余坚</a> 2010-06-21 10:28 <a href="http://www.blogjava.net/yuoveyu/archive/2010/06/21/324046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>