191145686 发表于 2017-1-15 12:32:46

Tomcat webAppClassloader

  WebappClassLoader  继承了URLClassLoader里面加入缓存和安全。
  缓存:
  1.缓存了已经事先装载的Classes。
  2.缓存了错误信息,比如先前装载一个类报错,那么下次再load这个类的时候,就会到缓存中去查找


  (   ClassNotFoundException






/**
* Load the class with the specified name.This method searches for
* classes in the same manner as <code>loadClass(String, boolean)</code>
* with <code>false</code> as the second argument.
*
* @param name Name of the class to be loaded
*
* @exception ClassNotFoundException if the class was not found
*/
public Class loadClass(String name) throws ClassNotFoundException {
return (loadClass(name, false));
}

/**
* Load the class with the specified name, searching using the following
* algorithm until it finds and returns the class.If the class cannot
* be found, returns <code>ClassNotFoundException</code>.
* <ul>
* <li>Call <code>findLoadedClass(String)</code> to check if the
*   class has already been loaded.If it has, the same
*   <code>Class</code> object is returned.</li>
* <li>If the <code>delegate</code> property is set to <code>true</code>,
*   call the <code>loadClass()</code> method of the parent class
*   loader, if any.</li>
* <li>Call <code>findClass()</code> to find this class in our locally
*   defined repositories.</li>
* <li>Call the <code>loadClass()</code> method of our parent
*   class loader, if any.</li>
* </ul>
* If the class was found using the above steps, and the
* <code>resolve</code> flag is <code>true</code>, this method will then
* call <code>resolveClass(Class)</code> on the resulting Class object.
*
* @param name Name of the class to be loaded
* @param resolve If <code>true</code> then resolve the class
*
* @exception ClassNotFoundException if the class was not found
*/
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
if (log.isDebugEnabled())
log.debug("loadClass(" + name + ", " + resolve + ")");
Class clazz = null;
// Log access to stopped classloader
if (!started) {
try {
throw new IllegalStateException();
} catch (IllegalStateException e) {
log.info(sm.getString("webappClassLoader.stopped", name), e);
}
}
// (0) Check our previously loaded local class cache
   //在这里装载的时候使用了缓存,注意这个是local class

clazz = findLoadedClass0(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug("Returning class from cache");
if (resolve)
resolveClass(clazz);
return (clazz);
}
// (0.1) Check our previously loaded class cache
//而这个就是class

clazz = findLoadedClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug("Returning class from cache");
if (resolve)
resolveClass(clazz);
return (clazz);
}
// (0.2) Try loading the class with the system class loader, to prevent
//       the webapp from overriding J2SE classes
try {
clazz = system.loadClass(name);
if (clazz != null) {
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
// Ignore
}
// (0.5) Permission to access this class when using a SecurityManager
    //安全机制

if (securityManager != null) {
int i = name.lastIndexOf('.');
if (i >= 0) {
try {
securityManager.checkPackageAccess(name.substring(0,i));
} catch (SecurityException se) {
String error = "Security Violation, attempt to use " +
"Restricted Class: " + name;
log.info(error, se);
throw new ClassNotFoundException(error, se);
}
}
}
boolean delegateLoad = delegate || filter(name);
// (1) Delegate to our parent if requested
//代理装载类

if (delegateLoad) {
if (log.isDebugEnabled())
log.debug("Delegating to parent classloader1 " + parent);
ClassLoader loader = parent;
if (loader == null)
loader = system;
try {
clazz = loader.loadClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug("Loading class from parent");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
// (2) Search local repositories
if (log.isDebugEnabled())
log.debug("Searching local repositories");
try {
clazz = findClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug("Loading class from local repository");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
// (3) Delegate to parent unconditionally
if (!delegateLoad) {
if (log.isDebugEnabled())
log.debug("Delegating to parent classloader at end: " + parent);
ClassLoader loader = parent;
if (loader == null)
loader = system;
try {
clazz = loader.loadClass(name);
if (clazz != null) {
if (log.isDebugEnabled())
log.debug("Loading class from parent");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
throw new ClassNotFoundException(name);
}
   看看WebAppClassLoader是如何从缓存中装载的

    /**
* Finds the class with the given name if it has previously been
* loaded and cached by this class loader, and return the Class object.
* If this class has not been cached, return <code>null</code>.
*
* @param name Name of the resource to return
*/
protected Class findLoadedClass0(String name) {
//resouceEntries是个hashmap

ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
if (entry != null) {
return entry.loadedClass;
}
return (null);// FIXME - findLoadedResource()
}

//看看缓存对象的代码
import java.net.URL;
import java.security.cert.Certificate;
import java.util.jar.Manifest;
/**
* Resource entry.
*
* @author Remy Maucherat
* @version $Revision: 302726 $ $Date: 2004-02-27 15:59:07 +0100 (ven., 27 f茅vr. 2004) $
*/
public class ResourceEntry {

/**
* The "last modified" time of the origin file at the time this class
* was loaded, in milliseconds since the epoch.
*/
public long lastModified = -1;

/**
* Binary content of the resource.
*/
public byte[] binaryContent = null;

/**
* Loaded class.
*/
public Class loadedClass = null;

/**
* URL source from where the object was loaded.
*/
public URL source = null;

/**
* URL of the codebase from where the object was loaded.
*/
public URL codeBase = null;

/**
* Manifest (if the resource was loaded from a JAR).
*/
public Manifest manifest = null;

/**
* Certificates (if the resource was loaded from a JAR).
*/
public Certificate[] certificates = null;
}


   安全机制



/**
* The set of trigger classes that will cause a proposed repository not
* to be added if this class is visible to the class loader that loaded
* this factory class.Typically, trigger classes will be listed for
* components that have been integrated into the JDK for later versions,
* but where the corresponding JAR files are required to run on
* earlier versions.
*/
protected static final String[] triggers = {
"javax.servlet.Servlet"                     // Servlet API
};
//这个在Tomcat4中有,在tomcat6.0中没有

private static final String[] packageTriggers = {
"javax",                                     // Java extensions
"org.xml.sax",                               // SAX 1 & 2
"org.w3c.dom",                               // DOM 1 & 2
"org.apache.xerces",                         // Xerces 1 & 2
"org.apache.xalan"                           // Xalan
};




 
页: [1]
查看完整版本: Tomcat webAppClassloader