Tomcat的classloader

1 - Tomcat的类载入器的结构

Tomcat Server在启动的时候将构造一个ClassLoader树,以保证模块的类库是私有的
Tomcat Server的ClassLoader结构如下:
其中:
- 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可见

2 - ClassLoader的工作原理

每个运行中的线程都有一个成员contextClassLoader,用来在运行时动态地载入其它类
系统默认的contextClassLoader是systemClassLoader,所以一般而言java程序在执行时可以使用JVM自带的类、$JAVA_HOME/jre/lib/ext/中的类和$CLASSPATH/中的类
可以使用Thread.currentThread().setContextClassLoader(...);更改当前线程的contextClassLoader,来改变其载入类的行为

ClassLoader被组织成树形,一般的工作原理是:
1) 线程需要用到某个类,于是contextClassLoader被请求来载入该类
2) contextClassLoader请求它的父ClassLoader来完成该载入请求
3) 如果父ClassLoader无法载入类,则contextClassLoader试图自己来载入

注意:WebApp?ClassLoader的工作原理和上述有少许不同:
它先试图自己载入类(在ContextBase?/WEB-INF/...中载入类),如果无法载入,再请求父ClassLoader完成

由此可得:
- 对于WEB APP线程,它的contextClassLoader是WebApp?ClassLoader
- 对于Tomcat Server线程,它的contextClassLoader是CatalinaClassLoader

3 - 部分原代码分析

3.1 - org/apache/catalina/startup/Bootstrap.java

Tomcat Server线程的起点
构造ClassLoader树,并设置Tomcat Server线程的contextClassLoader为catalinaloader
载入若干类,然后转入org.apache.catalina.startup.Catalina类中

---------------------------------------
 
None.gif package org.apache.catalina.startup;
None.gif
None.gif
// JDK类库
None.gif

None.gif
import java.io.File;
None.gif
import java.io.IOException;
None.gif
import java.lang.reflect.Method;
None.gif
import java.net.MalformedURLException;
None.gif
import java.net.URL;
None.gif
import java.util.ArrayList;
None.gif
None.gif
// apache自己的类库
None.gif

None.gif
import org.apache.catalina.loader.Extension;
None.gif
import org.apache.catalina.loader.StandardClassLoader;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/***/ /**
InBlock.gif*BoostraploaderforCatalina.Thisapplicationconstructsaclassloader
InBlock.gif*foruseinloadingtheCatalinainternalclasses(byaccumulatingallofthe
InBlock.gif*JARfilesfoundinthe"server"directoryunder"catalina.home"),and
InBlock.gif*startstheregularexecutionofthecontainer.Thepurposeofthis
InBlock.gif*roundaboutapproachistokeeptheCatalinainternalclasses(andany
InBlock.gif*otherclassestheydependon,suchasanXMLparser)outofthesystem
InBlock.gif*classpathandthereforenotvisibletoapplicationlevelclasses.
InBlock.gif*
InBlock.gif*
@authorCraigR.McClanahan
InBlock.gif*
@version$Revision:1.36$$Date:2002/04/0119:51:31$
ExpandedBlockEnd.gif
*/

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/***/ /**
InBlock.gif*该类的main方法的主要任务:--------------------------
InBlock.gif*
InBlock.gif*1,创建TOMCAT自己的类载入器(ClassLoader)+---------------------------+|Bootstrap|||||
InBlock.gif*System|||||Common||/\||CatalinaShared|
InBlock.gif*+---------------------------+其中:-Bootstrap-
InBlock.gif*载入JVM自带的类和$JAVA_HOME/jre/lib/ext/*.jar-System-载入$CLASSPATH/*.class-
InBlock.gif*Common-载入$CATALINA_HOME/common/dot.gif,它们对TOMCAT和所有的WEBAPP都可见-Catalina-
InBlock.gif*载入$CATALINA_HOME/server/dot.gif,它们仅对TOMCAT可见,对所有的WEBAPP都不可见-Shared-
InBlock.gif*载入$CATALINA_HOME/shared/dot.gif,它们仅对所有WEBAPP可见,对TOMCAT不可见(也不必见)
InBlock.gif*注意:当一个ClassLoader被请求载入一个类时,它首先请求其父ClassLoader完成载入,
InBlock.gif*仅当其父ClassLoader无法载入该类时,才试图自己载入该类2,改变本身线程的默认ClassLoader(本线程就是Tomcat
InBlock.gif*Server线程,类载入器是catalinaLoader)
InBlock.gif*3,让catalinaLoader载入一些类,类的位置在$CATALINA_HOME/server/lib/catalina.jar中
InBlock.gif*4,创建org.apache.catalina.startup.Catalina类的一个实例startupInstance,并为其调用方法:
InBlock.gif*startupInstance.setParentClassLoader(sharedLoader);
InBlock.gif*startupInstance.process(args);
InBlock.gif*
InBlock.gif*
InBlock.gif*有关ClassLoader的说明:-----------------------
InBlock.gif*
InBlock.gif*每个被DEPLOY的WEBAPP都会被创建一个ClassLoader,用来载入该WEBAPP自己的类
InBlock.gif*这些类的位置是webappX/WEB-INF/classes/*.class和webappX/WEB-INF/lib/*.jar
InBlock.gif*
InBlock.gif*ClassLoader的工作流程是:1)收到一个载入类的的请求2)请求其父ClassLoader来完成该类的载入3)
InBlock.gif*如果父ClassLoader无法载入,则自己试图完成该类的载入
InBlock.gif*
InBlock.gif*特别注意WEBAPP自己的ClassLoader的实现与众不同:它先试图从WEBAPP自己的目录里载入,如果失败则请求父ClassLoader的代理
InBlock.gif*这样可以让不同的WEBAPP之间的类载入互不干扰
InBlock.gif*
InBlock.gif*WEBAPP的ClassLoader的层次结构是:+----------------------------+|Shared||/\
InBlock.gif*dot.gif||Webapp1Webapp2dot.gif|+----------------------------+故对于一个WEB
InBlock.gif*APP,其类载入的优先顺序如下:-/WEB-INF/classes/*.class和/WEB-INF/lib/*.jar-Bootstrap
InBlock.gif*classesofJVM-Systemclassloaderclasses-$CATALINA_HOME/common/dot.gif-
InBlock.gif*$CATALINA_HOME/shared/dot.gif
InBlock.gif*
InBlock.gif*
InBlock.gif*小结:------
InBlock.gif*
InBlock.gif*综上分析-TomcatServer线程使用的classLoader是Catalina-每个WEB
InBlock.gif*APP线程使用的classloader是Webapp?
InBlock.gif*
ExpandedBlockEnd.gif
*/

None.gif
ExpandedBlockStart.gifContractedBlock.gif
public final class Bootstrap dot.gif {
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/***//**
InBlock.gif*DEBUG级别
ExpandedSubBlockEnd.gif
*/

InBlock.gif
InBlock.gif
privatestaticintdebug=0;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/***//**
InBlock.gif*脚本执行该程序时,提供以下的系统属性:java.endorsed.dirs="$JAVA_ENDORSED_DIRS"-classpath
InBlock.gif*"$CLASSPATH"\java.security.manager\
InBlock.gif*java.security.policy=="$CATALINA_BASE"/conf/catalina.policy\
InBlock.gif*catalina.base="$CATALINA_BASE"\catalina.home="$CATALINA_HOME"\
InBlock.gif*java.io.tmpdir="$CATALINA_TMPDIR"\
InBlock.gif*
InBlock.gif*
@paramargs
InBlock.gif*Commandlineargumentstobeprocessed
ExpandedSubBlockEnd.gif
*/

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
publicstaticvoidmain(Stringargs[])dot.gif{
InBlock.gif
InBlock.gif
//设置debug
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
for(inti=0;i<args.length;i++)dot.gif{
InBlock.gif
if("-debug".equals(args[i]))
InBlock.gifdebug
=1;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
//设置好系统属性catalina.base,即保证其有值
InBlock.gif

InBlock.gif
if(System.getProperty("catalina.base")==null)
InBlock.gifSystem.setProperty(
"catalina.base",getCatalinaHome());
InBlock.gif
InBlock.gif
//创建三个ClassLoader
InBlock.gif
//这三个对象是通过ClassLoaderFactory的静态方法创建的
InBlock.gif
//其实际类型是StandardClassLoader,完成tomcat自定义的类载入
InBlock.gif
//这些类对非tomcat及其上的webapp的其它java程序不可见,故用自己的Classloader载入
InBlock.gif

InBlock.gifClassLoadercommonLoader
=null;
InBlock.gifClassLoadercatalinaLoader
=null;
InBlock.gifClassLoadersharedLoader
=null;
ExpandedSubBlockStart.gifContractedSubBlock.gif
trydot.gif{
InBlock.gif
InBlock.gifFileunpacked[]
=newFile[1];
InBlock.gifFilepacked[]
=newFile[1];
InBlock.gifFilepacked2[]
=newFile[2];
InBlock.gif
InBlock.gifClassLoaderFactory.setDebug(debug);
InBlock.gif
InBlock.gif
//$CATALINA_HOME/common/classes/*.class-未压缩的类
InBlock.gif
//$CATALINA_HOME/common/endorsed/*.jar-压缩的类(endorse:支持)
InBlock.gif
//$CATALINA_HOME/common/lib/*.jar-压缩的类
InBlock.gif
//这些类是被tomcatserver以及所有的webapp所共享的类,由commonLoader负责载入
InBlock.gif

InBlock.gifunpacked[
0]=newFile(getCatalinaHome(),"common"+File.separator
InBlock.gif
+"classes");
InBlock.gifpacked2[
0]=newFile(getCatalinaHome(),"common"+File.separator
InBlock.gif
+"endorsed");
InBlock.gifpacked2[
1]=newFile(getCatalinaHome(),"common"+File.separator
InBlock.gif
+"lib");
InBlock.gifcommonLoader
=ClassLoaderFactory.createClassLoader(unpacked,
InBlock.gifpacked2,
null);
InBlock.gif
InBlock.gif
//$CATALINA_HOME/server/classes/*.class
InBlock.gif
//$CATALINA_HOME/server/lib/*.jar
InBlock.gif
//这些类是仅被tomcatserver使用而对webapp不可见的类,由catalinaLoader负责载入
InBlock.gif

InBlock.gifunpacked[
0]=newFile(getCatalinaHome(),"server"+File.separator
InBlock.gif
+"classes");
InBlock.gifpacked[
0]=newFile(getCatalinaHome(),"server"+File.separator
InBlock.gif
+"lib");
InBlock.gifcatalinaLoader
=ClassLoaderFactory.createClassLoader(unpacked,
InBlock.gifpacked,commonLoader);
InBlock.gif
InBlock.gif
//$CATALINA_BASE/shared/classes/*.class
InBlock.gif
//$CATALINA_BASE/shared/lib/*.jar
InBlock.gif
//这些类是仅被tomcat的webapp使用的类,由sharedLoader负责载入
InBlock.gif

InBlock.gifunpacked[
0]=newFile(getCatalinaBase(),"shared"+File.separator
InBlock.gif
+"classes");
InBlock.gifpacked[
0]=newFile(getCatalinaBase(),"shared"+File.separator
InBlock.gif
+"lib");
InBlock.gifsharedLoader
=ClassLoaderFactory.createClassLoader(unpacked,
InBlock.gifpacked,commonLoader);
InBlock.gif
InBlock.gif
//注意三个自己定置的ClassLoader的层次关系:
InBlock.gif
//systemClassLoader(root)
InBlock.gif
//+---commonLoader
InBlock.gif
//+---catalinaLoader
InBlock.gif
//+---sharedLoader
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif}
catch(Throwablet)dot.gif{
InBlock.giflog(
"Classloadercreationthrewexception",t);
InBlock.gifSystem.exit(
1);
InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
//为当前的线程更改其contextClassLoader
InBlock.gif
//一般的线程默认的contextClassLoader是系统的ClassLoader(所有其它自定义ClassLoader的父亲)
InBlock.gif
//当该线程需要载入类时,将使用自己的contextClassLoader来寻找并载入类
InBlock.gif
//更改contextClassLoader可以更改该线程的寻找和载入类的行为,但不影响到其它线程
InBlock.gif
//注意!TomcatServer线程使用的是catalinaLoader
InBlock.gif

InBlock.gifThread.currentThread().setContextClassLoader(catalinaLoader);
InBlock.gif
InBlock.gif
//Loadourstartupclassandcallitsprocess()method
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
trydot.gif{
InBlock.gif
InBlock.gif
//预载入catalinalLoader的一些类
InBlock.gif

InBlock.gifSecurityClassLoad.securityClassLoad(catalinaLoader);
InBlock.gif
InBlock.gif
//获得tomcat的启动类:org.apache.catalina.startup.Catalina,并创建该类的一个实例
InBlock.gif

InBlock.gif
if(debug>=1)
InBlock.giflog(
"Loadingstartupclass");
InBlock.gifClassstartupClass
=catalinaLoader
InBlock.gif.loadClass(
"org.apache.catalina.startup.Catalina");
InBlock.gifObjectstartupInstance
=startupClass.newInstance();
InBlock.gif
InBlock.gif
//设置startupInstance的父ClassLoader,相当于执行:
InBlock.gif
//CatalinastartupInstance=newCatailina();
InBlock.gif
//startupInstance.setParentClassLoader(sharedLoader);
InBlock.gif
//详情参考类org.apache.catalina.startup.Catalina
InBlock.gif

InBlock.gif
if(debug>=1)
InBlock.giflog(
"Settingstartupclassproperties");
InBlock.gifStringmethodName
="setParentClassLoader";
InBlock.gifClassparamTypes[]
=newClass[1];
InBlock.gifparamTypes[
0]=Class.forName("java.lang.ClassLoader");
InBlock.gifObjectparamValues[]
=newObject[1];
InBlock.gifparamValues[
0]=sharedLoader;
InBlock.gifMethodmethod
=startupInstance.getClass().getMethod(methodName,
InBlock.gifparamTypes);
InBlock.gifmethod.invoke(startupInstance,paramValues);
InBlock.gif
InBlock.gif
//使用main方法获得的参数args来执行process方法,相当于:
InBlock.gif
//startupInstance.process(args);
InBlock.gif
//详情参考类org.apache.catalina.startup.Catalina
InBlock.gif

InBlock.gif
if(debug>=1)
InBlock.giflog(
"Callingstartupclassprocess()method");
InBlock.gifmethodName
="process";
InBlock.gifparamTypes
=newClass[1];
InBlock.gifparamTypes[
0]=args.getClass();
InBlock.gifparamValues
=newObject[1];
InBlock.gifparamValues[
0]=args;
InBlock.gifmethod
=startupInstance.getClass().getMethod(methodName,
InBlock.gifparamTypes);
InBlock.gifmethod.invoke(startupInstance,paramValues);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif}
catch(Exceptione)dot.gif{
InBlock.gifSystem.out.println(
"Exceptionduringstartupprocessing");
InBlock.gife.printStackTrace(System.out);
InBlock.gifSystem.exit(
2);
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/***//**
InBlock.gif*返回$CATALINA_HOME变量。如果该变量没有定义,则将之赋值为用户的当前工作目录。
ExpandedSubBlockEnd.gif
*/

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
privatestaticStringgetCatalinaHome()dot.gif{
InBlock.gif
returnSystem.getProperty("catalina.home",System
InBlock.gif.getProperty(
"user.dir"));
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/***//**
InBlock.gif*返回$CATALINA_BASE变量。如果该变量没有定义,则将之赋值为$CATALINA_HOME。
ExpandedSubBlockEnd.gif
*/

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
privatestaticStringgetCatalinaBase()dot.gif{
InBlock.gif
returnSystem.getProperty("catalina.base",getCatalinaHome());
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/***//**
InBlock.gif*输出LOG信息。
ExpandedSubBlockEnd.gif
*/

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
privatestaticvoidlog(Stringmessage)dot.gif{
InBlock.gif
InBlock.gifSystem.out.print(
"Bootstrap:");
InBlock.gifSystem.out.println(message);
InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/***//**
InBlock.gif*输出由异常引起的LOG信息。
ExpandedSubBlockEnd.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值