How Tomcat Works 读书笔记 八 载入器(二)

2015-01-27 14:06:04 · 作者: · 浏览: 59
break; try { // Perform our modification check if (!classLoader.modified()) continue; } catch (Exception e) { log(sm.getString(webappLoader.failModifiedCheck), e); continue; } // Handle a need for reloading notifyContext(); break; } if (debug >= 1) log(BACKGROUND THREAD Stopping); } private void threadSleep() { //让程序休眠一段时间 时间由checkInterval指定 try { Thread.sleep(checkInterval * 1000L); } catch (InterruptedException e) { ; } }
checkInterval,是每隔若干秒来检查一次容器中的类是否有更改!
一旦有更改classLoader.modified()会返回true,直接调用notifyContext();
 private void notifyContext() {
        WebappContextNotifier notifier = new WebappContextNotifier();
        (new Thread(notifier)).start();
    }
protected class WebappContextNotifier implements Runnable {

        /**
         * Perform the requested notification.
         */
        public void run() {
            ((Context) container).reload();
        }
    }
WebappContextNotifier是webapploader的内部类。
这里重新启了一个线程,避免了拥塞。

WebappClassLoader类

该类继承自java.net.URLClassLoader类,后者我们在前面章节已经用过;
WebappClassLoader类的设计考虑了安全与优化两个方面。
WebappClassLoader 类不允许一些特定的类被加载。这些类被存储在一个 String 类型的数组中,现在仅仅有一个成员。
private static final String[] triggers = {
javax.servlet.Servlet // Servlet API
};
另外在委派给系统加载器的时候,也不允许加载某些特殊的包的类或者它的子包:
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
};

类缓存

为了达到更好的性能,会缓存已经载入的类,这样一来下次在使用这个类的时候,就不用再起加载了。

缓存分两级,一级在本地执行,由webappclassloader实例来管理。
此外,java.lang.ClassLoader类也会维护一个Vector对象,保存已经载入的类,此时缓存由父类管理。

每个由WebappClassLoader载入的类,都视为资源。是org.apache.catalina.loader.ResourceEntry类的实例,里面包含所代表的class文件的字节流,最后一次修改时间等等:
package org.apache.catalina.loader;
import java.net.URL;
import java.security.cert.Certificate;
import java.util.jar.Manifest;
public class ResourceEntry {
    public long lastModifled = -1;
    // Binary content of the resource.public byte[] binaryContent = null;
    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;
    public Manifest manifest = null;
    public Certificate[] certificates = null;
}


所有缓存的源被存放在一个叫做 resourceEntries 的 HashMap 中,键值为载入的资源名称,所有找不到的资源都被放在一个名为 notFoundResources 的 HashMap 中。



至于真正的加载类,我们放在下一节说。


参考资料

http://my.oschina.net/xianggao/blog/70826