Tomcat 类加载过程

以下内容部分来自网络,如有侵权,请站内联系。

Tomcat 下的工程,使用 WebappClassLoader 进行类的加载。查看 WebappClassLoader 源码,可以总结出 Tomcat 的类加载过程如下:
1. 先在自己(即当前 WebappClassLoader)的缓存中查找,有则返回,无则继续;
2. 再递归地在 parent 的缓存中查找,有则返回,无则继续;
3. 缓存中没有。尝试使用 sun.misc.Launcher$AppClassLoader 加载,成功则返回,失败则继续;
这样做的目的是,避免工程中重写了 Java 基础类,造成混乱。换句话说, webapp 下的 java.lang.* 等将被委托给上层的类加载器( ExtClassLoader 或 LaunchClassLoader 等)加载,这样就保证了基础类的安全。请放心,这里 sun.misc.Launcher$AppClassLoader 是不会加载到 webapp 中用户自定义的类的:我们知道 sun.misc.Launcher$AppClassLoader 是用来加载 classpath 中的类的,但 tomcat 消除了 classpath 的概念。
4. 一般情况下,调用自己的 findClass() 方法进行加载,成功则返回,失败则继续;
5. 若自己加载失败,递归请求 parent 进行加载;
6. 若最终都没能加载成功,则抛出 ClassNotFoundException 。

从4、5两步可以看出, Tomcat 的类加载过程和 Java 经典的类加载策略是有出入的,它在一定程度上破坏了双亲委派模型。这样做的目的是为了迎合 Servlet 规范,应用程序类的优先级要高于容器中类的优先级。

一个 WebappClassLoader 对应着一个 Web 应用程序,其父亲是 Tomcat 的 lib 的类加载器。所以 Tomcat 在默认情况下,不是完全按照先 Tomcat 的 lib 再 Web 应用的 lib 这种顺序去加载类的,正确的 Jar 包加载顺序是:
1. JRE 中的 Java 基础包;
2. Web 应用 WEB-INF\lib 下的包;
3. Tomcat\lib 下的包。
所以,如果想在 Web 应用间共享一些 Jar 包,不仅需要将公共包放在 Tomcat 的 lib 下,还要删掉 Web 应用 lib 下的包,否则 Tomcat 启动时还是会优先加载 Web 应用 lib 下的包的。

猜你喜欢

转载自dsxwjhf.iteye.com/blog/2202017
今日推荐