赞
踩
众所周知,Java中默认的类加载器是以父子关系存在的,实现了双亲委派机制进行类的加载,在前文中,我们提到了,双亲委派机制的设计是为了保证类的唯一性,这意味着在同一个JVM中是不能加载相同类库的不同版本的类。
然而与许多服务器应用程序一样,Tomcat 允许容器的不同部分以及在容器上运行的不同Web应用程序可以访问的各种不同版本的类库,这就要求Tomcat必须打破这种双亲委派机制,通过实现自定义的类加载器(即实现了java.lang.ClassLoader)进行类的加载。下面,就让我们来看看Tomcat类加载原理是怎样的。
Tomcat中有两个最重要的类加载器,第一个便是负责Web应用程序类加载的WebappClassLoader,另一个便是JSP Servlet类加载器`JasperLoader。
上代码:
- public class WebappClassLoader extends WebappClassLoaderBase {
- public WebappClassLoader() {
- super();
- }
- public WebappClassLoader(ClassLoader parent) {
- super(parent);
- }
- ...
- }
我们来看看WebappClassLoader继承的WebappClassLoaderBase中实现的类加载方法loadClass
- public abstract class WebappClassLoaderBase extends URLClassLoader
- implements Lifecycle, InstrumentableClassLoader, WebappProperties, PermissionCheck {
- ... 省略不需要关注的代码
- protected WebappClassLoaderBase() {
-
- super(new URL[0]);
- // 获取当前WebappClassLoader的父加载器系统类加载器
- ClassLoader p = getParent();
- if (p == null) {
- p = getSystemClassLoader();
- }
- this.parent = p;
- // javaseClassLoader变量经过以下代码的执行,
- // 得到的是扩展类加载器(ExtClassLoader)
- ClassLoader j = String.class.getClassLoader();
- if (j == null) {
- j = getSystemClassLoader();
- while (j.getParent() != null) {
- j = j.getParent();
- }
- }
- this.javaseClassLoader = j;
-
- securityManager = System.getSecurityManager();
- if (securityManager != null) {
- refreshPolicy();
- }
- }
-
- ...省略不需要关注的代码
- @Override
- public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
-
- synchronized (getClassLoadingLock(name)) {
- if (log.isDebugEnabled()) {
- log.debug("loadClass(" + name + ", " + resolve + ")");
- }
- Class<?> clazz = null;
-
- // Web应用程序停止状态时,不允许加载新的类
- checkStateForClassLoading(name);
-
- // 如果之前加载过该类,就可以从Web应用程序类加载器本地类缓存中查找,
- // 如果找到说明WebappClassLoader之前已经加载过这个类
- clazz = findLoadedClass0(name);
- if (clazz != null) {
- if (log.isDebugEnabled()) {
- log.debug(" Returning class from cache");
- }
- if (resolve) {
- resolveClass(clazz);
- }
- return clazz;
- }
-
- // Web应用程序本地类缓存中没有,可以从系统类加载器缓存中查找,
- // 如果找到说明AppClassLoader之前已经加载过这个类
- clazz = findLoadedClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled()) {
- log.debug(" Returning class from cache");
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。