当前位置:首页 > 开发 > 系统架构 > 架构 > 正文

Tomcat 5.0.18 ClassLoader source code insight

发表于: 2015-07-13   作者:DavyJones2010   来源:转载   浏览次数:
摘要: All the functionality of ClassLoader is nested in org.apache.catalina.loader.WebappClassLoader 1) Structure of WebappClassLoader public class WebappClassLoader extends URLClassLoader

All the functionality of ClassLoader is nested in org.apache.catalina.loader.WebappClassLoader

1) Structure of WebappClassLoader

public class WebappClassLoader
    extends URLClassLoader
    implements Lifecycle{
  /**
     * The cache of ResourceEntry for classes and resources we have loaded,
     * keyed by resource name.
     */
    protected HashMap resourceEntries = new HashMap();
    /**
     * The list of not found resources.
     */
    protected HashMap notFoundResources = new HashMap();
    public Class loadClass(String name, boolean resolve);
    protected Class findLoadedClass0(String name);
    public Class findClass(String name);
    protected Class findClassInternal(String name);

    // This method is derived from java.lang.ClassLoader; it will invoke native method searching JVM for classes loaded by current class loaders
    // It will return the loaded class if and only if the class is previously loaded(call defineClass method) by current class loader instance
    protected final Class<?> findLoadedClass(String name);
    // This method is derived from java.lang.ClassLoader, it will invoke native method  and it is the only way of converting byte[] into Class<?>; even if in our self defined ClassLoader.
    protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                         ProtectionDomain protectionDomain);
}

2) Overrides loadClass() on URLClassLoader

public Class loadClass(String name, boolean resolve){
  // (0) Check local class cache
  clazz = findLoadedClass0(name);
  if (clazz != null) {
      return (clazz);
  }
  // (0.1) Check ClassLoader inherent cache, call native method
  clazz = findLoadedClass(name);
  if (clazz != null) {
      return (clazz);
  }

  // Here we can guarantee that target class hasn't been loaded by WebAppClassLoader before, but whether it has been loaded by System/Ext/Bootstrap ClassLoader is unknown
  // Try to find class from bootstrap/ext/system ClassLoader's inherent cache, if cannot find, try to load .class from class path; throw exception when cannot be load either
  try {
       clazz = system.loadClass(name);
       return (clazz);
   } catch (ClassNotFoundException e) {
        // Ignore
   }

  // Here we are sure that the target class hasn't loaded by current application before.
  // We will try to load it from container's WEB-INF/libs

  // delegateLoad means WebappClassLoader will use parent first model, if false, means WebappClassLoader will use child first model.
  boolean delegateLoad = delegate || filter(name);

  // load class with parent
  if (delegateLoad) {
    try{
      clazz = parent.loadClass(name);
      if (clazz != null) {
         return (clazz);
      }
    }catch(ClassNotFoundException e){
      // swallow e
    }
  }
  // load class with child(It is the end of parent delegation, and it is the start of child first)
  try {
      clazz = findClass(name);
      if (clazz != null) {
          return (clazz);
      }
  } catch (ClassNotFoundException e) {
      ;
  }

  // load class with parent(It is then end of child first model)
  if (!delegateLoad) {
      ClassLoader loader = parent;
      try {
         clazz = loader.loadClass(name);
          if (clazz != null) {
              return (clazz);
          }
      } catch (ClassNotFoundException e) {
          ;
      }
  }
  // All possible tries has failed, throw exception
  throw new ClassNotFoundException(name);
}

// get class from WebappClassLoader customized class cache
protected Class findLoadedClass0(String name) {
  ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
  if (entry != null) {
        return entry.loadedClass;
  }
  return (null);  // FIXME - findLoadedResource()
}

3) How tomcat class reload works? Take a look at WebappClassLoader.stop()/start() as it implements interface Lifecycle;

// All ClassLoader did is clear its local class cache because we do not have the access to inherited java.lang.ClassLoader's inherent cache.
// reload is realized by calling stop() and start(), then loadClass() loading all classes under WEB-INF/lib
// loadClass(name) will first check local class cache which will return null, then it will check inherent cache, that would return "null" because 
// every time we restart, our WebappClassLoader is newly instantiated(the old instance is discarded)
public void stop(){
  started = false;
  notFoundResources.clear();
  resourceEntries.clear();
  repositoryURLs = null;
}
public void start() throws LifecycleException {
  started = true;
}

   The logic where a new WebappClassLoader instance is created every time the container is restarted:

// WebappLoader
public void start(){
  classLoader = createClassLoader();
  classLoader.setResources(container.getResources());
  classLoader.setDebug(this.debug);
  classLoader.setDelegate(this.delegate);
  // ...
  if (classLoader instanceof Lifecycle)
    ((Lifecycle) classLoader).start();
}
/**
* Create associated classLoader.
*/
private WebappClassLoader createClassLoader()
  throws Exception {
  Class clazz = Class.forName(loaderClass);
  WebappClassLoader classLoader = null;

  if (parentClassLoader == null) {
    parentClassLoader = Thread.currentThread().getContextClassLoader();
  }
  Class[] argTypes = { ClassLoader.class };
  Object[] args = { parentClassLoader };
  Constructor constr = clazz.getConstructor(argTypes);
  classLoader = (WebappClassLoader) constr.newInstance(args);

  return classLoader;
}

 

 

Summary:

1) We do not have direct access to native class cache defined by JVM. But we can make a little tweaks to realize class loading:

    1> We can suppose the native class cache keeps a map of Map<String, Class> with key of ClassLoader.instance.hashCode[classname+instancecode], and value of loaded class.

    2> The class would be recorded into native cache when the class loader's instance calls defineClass(), and the cached class would be returned only when current class loader instance calls findLoadedClass0();

 

Tomcat 5.0.18 ClassLoader source code insight

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
原文地址:http://www.tomcatexpert.com/blog/2012/12/05/use-spring-insight-developer-analyze-co
Source insight最新版本3572 下载链接:http://www.sourceinsight.com/down35.html, http://www.sour
准备好好研究学习一下tomcat 7 的源代码,那么第一步就是下载,导入eclipse并且运行。 1. 下载源代码
准备好好研究学习一下tomcat 7 的源代码,那么第一步就是下载,导入eclipse并且运行。 1. 下载源代码
Tomcat6.0源码学习--Connector架构 概述 Tomcat虽然具有传统Web服务器(如Apache)的功能(处理Html
Tomcat6.0源码学习--启动框架 摘要 对于独立运行的应用程序来说,都有一个入口,以便启动应用程序。
转:http://blog.csdn.net/goldfighter/article/details/7847168 目录 source insight代码对齐Tab键
Sunirvana 标签: Source Insight中一些好用宏的使用 1、 把indent.em、NetEyeutils.em、utils.em放
使用Source insight的时候想看文件的全路径,但是默认的是中间省略的路径,所以可以通过: 1.Option
习惯了在source insight下编辑阅读源码,在linux下用vi总是用不好 ,还是在ubuntu上用回熟悉的sourc
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号