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();
相关推荐
jakarta-tomcat-5.0.18.exe
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,目前最新版本是6.0.20(截止到2009-03-20)。 Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和...
源码部分包括了Tomcat 4.1.12和5.0.18两个版本,这两个版本分别代表了Tomcat发展的不同阶段。4.1.12是Tomcat 4系列的一个稳定版本,5.0.18则是Tomcat 5系列的重要版本,引入了许多新特性和性能优化。源码的提供使得...
HowTomcatWorks书籍课程...书籍剖析了Tomcat 4.1.12和Tomcat 5.0.18--一个免费的、开源的、深受大众欢迎的、代号为Catalina的servlet容器,并讲解其容器的内部运行机制。通过迭代实现一个简化版软件来讲述相应原理。
mysql5.0.18
1. 环境准备:需要有两台安装Windows 2008 R2操作系统的服务器,每台服务器需要安装JDK 1.6.20、Tomcat 5.0.18和Apache 2.2.3软件。两台服务器的IP地址分别为***.***.***.*和***.***.***.*,虚拟IP地址为***.***.***...
MySQL 5.0.18 是 MySQL 数据库管理系统的一个历史版本。MySQL 是一款开源、免费的关系型数据库管理系统,广泛应用于互联网行业中,特别是网站和应用程序的数据存储。它的特点是速度快、稳定性好、易于使用,并且支持...
Tomcat4.1.12和Tomcat5.0.18版本是书中具体剖析的对象。Tomcat的内核代号为Catalina,是一个免费的开源servlet容器,也是目前最受欢迎的servlet容器之一。 Tomcat的内部结构分为多个组件,作者提出通过创建每一个...
该书基于Tomcat 4.1.12和5.0.18两个版本,深入讲解了其servlet容器的架构和运作原理,尤其是代号为Catalina的核心组件。 Tomcat是一个开源的Java应用服务器,主要用于部署和运行基于Servlet和JavaServer Pages (JSP...
mysql-5.0.18源码,共两部分,这是分卷1.
《Easy Touch 5.0.18:Unity的高效交互工具》 在Unity游戏开发领域,易用性和玩家体验是至关重要的因素。Easy Touch 5.0.18是一款专为Unity设计的最新版本插件,它极大地提升了游戏的触摸交互功能,为开发者提供了...