Tomcat类加载器
Tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。
对于JVM来说:
因此,按照这个过程可以想到,如果同样在CLASSPATH指定的目录中和自己工作目录中存放相同的class,会优先加载CLASSPATH目录中的文件。
像许多服务器应用程序一样,Tomcat安装了各种类加载器(即实现的类java.lang.ClassLoader),以允许容器的不同部分以及容器上运行的Web应用程序可以访问可用类和资源的不同存储库。该机制用于提供Servlet规范2.4版中定义的功能-特别是9.4和9.6节。
在Java环境中,类加载器排列在父子树中。通常,当要求类加载器加载特定的类或资源时,它首先将请求委派给父类加载器,然后仅在父类加载器找不到所请求的类或资源时才在其自己的存储库中查找。请注意,Web应用程序类加载器的模型与此略有不同,如下所述,但是主要原理是相同的。
Tomcat启动时,它将创建一组类加载器,这些类加载器被组织为以下父子关系,其中父类加载器位于子类加载器之上:
Common类加载器,负责加载Tomcat和Web应用都复用的类
Catalina类加载器,负责加载Tomcat专用的类,而这些被加载的类在Web应用中将不可见
Shared类加载器,负责加载Tomcat下所有的Web应用程序都复用的类,而这些被加载的类在Tomcat中将不可见
WebApp类加载器,负责加载具体的某个Web应用程序所使用到的类,而这些被加载的类在Tomcat和其他的Web应用程序都将不可见
Jsp类加载器,每个jsp页面一个类加载器,不同的jsp页面有不同的类加载器,方便实现jsp页面的热插拔
从图中的委派关系中可以看出:CommonClassLoader能加载的类都可以被Catalina
ClassLoader和SharedClassLoader使用,从而实现了公有类库的共用,而CatalinaClassLoader和Shared
ClassLoader自己能加载的类则与对方相互隔离。WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离。
而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能。
> > 进阶设定
也可以配置更复杂的类加载器层次结构。请参见下图。默认情况下,
未定义服务器和共享类加载器,并且使用上面显示的简化层次结构。通过为中的server.loader和/或shared.loader属性
定义值,可以使用这种更复杂的层次结构 conf/catalina.properties。Bootstrap
|
System
|
Common
/ \ Server Shared
/ \ Webapp1 Webapp2 … 该服务器类加载器是唯一到Tomcat内部可见,并且是Web应用程序完全不可见。所述共享类加载器是将所有的web应用程序可见,并且可以在所有的web应用程序被用来共享代码。但是,对此共享代码的任何更新都将要求Tomcat重新启动。