在了解类加载机制时,发现网上大部分文章还停留在tomcat6,甚至tomcat5。
Tomcat8 和 Tomcat6比较大的区别是 :
- Tomcat8可以通过配置 <Loader delegate="true"/>不打破双亲委托
- 类的加载顺序略不同
概述
在 Java 环境中,类加载器的布局结构是一种父子树的形式。通常,类加载器被请求加载一个特定的类或资源时,它会先把这一请求委托给它的父类加载器,只有(一个或多个)父类加载器无法找到请求的类或资源时,它才开始查看自身的仓库。
Web应用程序类加载器的模型与此略有不同,如下所述,但主要原则是相同的。
类加载器定义
Bootstrap
加载JVM启动所需的类和系统扩展目录($JAVA_HOME/jre/lib/ext)里 JAR 文件中的类
System
加载tomcat启动的类
Common
加载对Tomcat内部类和所有Web应用程序都可见的其他类 所有应用共享 JAR文件 $CATALINA_HOME/lib JAR文件 $CATALINA_BASE/lib
WebappX
为部署在单个Tomcat实例中的每个Web应用程序创建一个类加载器 加载WEB-INF/classes和WEB-INF/lib的jar中的类 应用私有
查找顺序
代码语言:javascript复制 Bootstrap
|
System
|
Common
/
Webapp1 Webapp2 ...
Tomcat打破了双亲委派顺序
当某个请求想从 Web 应用的 WebappX 类加载器中加载类时,该类加载器会先查看自己的仓库,而不是预先进行委托处理
Tomcat8
- JVM 的 Bootstrap 类
- Web 应用的 /WEB-INF/classes 类
- Web 应用的 /WEB-INF/lib/.jar 类*
- System 类加载器的类
- Common 类加载器的类
例:
在 /WEB-INF/classes中有一个应用内部自定义的FileUpload类, Common 中也有一个共享的FileUpload类。
Tomcat8加载顺序:
- 在加载时,先不进行委托,则每个应用会加载自己的类(2/3 Web加载器)
- 加载不到时委托到再上层Common,Common再委托至System,
- 4 System加载到就返回,加载不到再让Common处理
- 5 Common加载到就返回,加载不到抛出异常
问题:
顺序1哪去了?为什么不再委托至Bootstrap 呢?
主要是为了防止一些基础类会被web中的类覆盖
如果web自定义一个Object类呢?首先查找web加载器,就会出问题了。
所以在加载时最先交给Bootstrap加载器加载。
遵循双亲委托
如果 Web 应用类加载器配置有 <Loader delegate="true"/>,表示遵从双亲委托机制,同JVM,则加载顺序变为:
- JVM 的 Bootstrap 类
- System 类加载器的类
- Common 类加载器的类
- Web 应用的 /WEB-INF/classes 类
- Web 应用的 /WEB-INF/lib/*.jar 类
例:
在 /WEB-INF/classes中有一个应用内部自定义的FileUpload类, Common 中也有一个共享的FileUpload类,
顺序:
严格按照双亲委派模型进行