The things I writing is virtually a practice base on Peter M.Chen's article. You can also see here
The reloading I talking about here is reloading the modified classes directly without reloading all the web application.
OK, let's go on step by step.
1) Download the source code of your current Tomcat. Please be sure the version is the same, or the best you can download a set of Tomcat binary and source togeher. For example download the tomcat 4.1.34 in the page: 2) Create a new class which the name is DynamicClassLoader
package org.apache.catalina.loader; import java.net.URL; import java.net.URLClassLoader; import java.security.CodeSource; import java.util.*; /** *//** * @author peter */ publicclass DynamicClassLoader extends URLClassLoader ...{ /**//* parent class loader, it's org.apache.catalina.loader.WebappClassLoader */ private ClassLoader parent =null; /**//* list of already loaded classes names */ private List classNames =null; /** *//** * * @param parent * * here isorg.apache.catalina.loader.WebappClassLoader * */ public DynamicClassLoader(ClassLoader parent) ...{ super(new URL[0]); classNames =new ArrayList(); this.parent = parent; } /** *//** * * this method will call in WebappClassLoader . * * * * @param name * * @param classData * * @param codeSource * * @return * * @throws ClassNotFoundException * */ public Class loadClass(String name, byte[] classData, CodeSource codeSource) throws ClassNotFoundException ...{ if (classNames.contains(name)) ...{ return loadClass(name); }else...{ classNames.add(name); return defineClass(name, classData, 0, classData.length, codeSource); } } /** *//** * * when a class not in classNames, let parent load it * * @see java.lang.ClassLoader#loadClass(java.lang.String) * */ public Class loadClass(String name) throws ClassNotFoundException ...{ if (!classNames.contains(name)) ...{ return parent.loadClass(name); } returnsuper.loadClass(name); } }
3) Append the code to be the end of org.apache.catalina.loader.WebappClassLoader
4) Find out the method findClass(String name) of WebappClassLoader. If it is private, set it to be public.
5) Find out the method findClassInternal(String name) of WebappClassLoader. Add the following line between the part of if (packageName != null) {} and CodeSource codeSource = new CodeSource(entry.codeBase, entry.certificates); :
if (isReload) removeResourceEntry(name);
6) Still in the method findClassInternal(String name) of WebappClassLoader, modify
if ((entry ==null) || (entry.binaryContent ==null))
to be
if ((entry ==null) || (entry.loadedClass ==null&& entry.binaryContent ==null))
7) Still in the method findClassInternal(String name) of WebappClassLoader, modfiy