[源码学习]Tomcat6 源码学习
Tomcat6源码学习
2010-3-29
【tomcat启动类Bootstrap】
t1.tomcat的人口函数,启动类
org.apache.catalina.startup.Bootstrap.javaMain函数
t2.Bootstrap类
初始化ClassLoader,然后利用JavaReflection调用Catalina类来启动tomcatserver
【tomcat扩展-日志】
a1.privatestaticLoglog=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时唯一需要覆盖的方法。
ClassLoaderloadClass方法
Classc=findLoadedClass(name);
if(c==null){
try{
if(parent!=null){
c=parent.loadClass(name,false);
}else{
c=findBootstrapClass0(name);
}
}catch(ClassNotFoundExceptione){
//Ifstillnotfound,theninvokefindClassinorder
//tofindtheclass.
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自定义了三个类,catalinaLoadercommonLoader,sharedLoader
Common-载入$CATALINA_HOME/common/...它们对TOMCAT和所有的WEBAPP都可见
Catalina-载入$CATALINA_HOME/server/..它们仅对TOMCAT可见,对所有的WEBAPP都不可见
Shared-载入$CATALINA_HOME/shared/它们仅对所有WEBAPP可见,对TOMCAT不可见(也不必见)
t4.Bootstrap通过反射初始化Catalina类,
反射调用Catalina方法setParentClassLoader,传递SharedClassloader
反射callCatalina方法load利用server.xml中的配置初始化Service,Server,Engine,Host
反射callCatalina方法startStartthenewserver该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'sListener:(监听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启动serverSocket,listern8080端口,处理http请求
4.Http11Processor
ProcessesHTTPrequests.
由http11ConnectionHandler调用,Http11ConnectionHandler由JioEndpoint中的Work调用
5.AconnectorpassestherequestandreponseobjectstotheContainerbycallingtheContainerinterface'sinvokemethod
publicvoidinvoke(Requestrequest,Responseresponse)
throwsIOException,ServletException;
insidetheinvokemethod,thecontainerloadstheservletclass,callitssevicemethod,managesessions,etc.
6.Connector方法initialize中
//Initializaadapter
adapter=newCoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
adapter通过protocolHandler(Http11Protocol)传给Http11Processor,
Http11Processor解析,createrequest和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
属性Pipelinepipeline=newStandardPipeline(this);
构造函数里会设置最底层的阀门
pipeline.setBasic(newStandardEngineValve());
如果需要设置新阀门处理需求,只需要调用pipeline.addValve(Valvevalve);
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线程】
/**
*ProcessanincomingTCP/IPconnectiononthespecifiedsocket.Any
*exceptionthatoccursduringprocessingmustbeloggedandswallowed.
*<b>NOTE</b>:ThismethodiscalledfromourConnector'sthread.We
*mustassignittoourownthreadsothatmultiplesimultaneous
*requestscanbehandled.
*@paramsocketTCPsockettoprocess
*/
synchronizedvoidassign(Socketsocket){
//WaitfortheProcessortogetthepreviousSocket
while(available){
try{
wait();
}catch(InterruptedExceptione){
}
}
//StorethenewlyavailableSocketandnotifyourthread
this.socket=socket;
available=true;
notifyAll();
}
/**
*AwaitanewlyassignedSocketfromourConnector,or<code>null</code
*ifwearesupposedtoshutdown.
*/
privatesynchronizedSocketawait(){
//WaitfortheConnectortoprovideanewSocket
while(!available){
try{
wait();
}catch(InterruptedExceptione){
}
}
//NotifytheConnectorthatwehavereceivedthisSocket
Socketsocket=this.socket;
available=false;
notifyAll();
return(socket);
}
连接器线程调用worker类的assign类,worker类的执行线程run方法会调用await方法获取socket,通过available变量的设置和wait/notify方法来协调彼此的操作。当连接器线程未传输socket,worker类线程就执行wait等待,
当worker类执行线程在处理忙的时候,连接器线程wait。