《How Tomcat Works》读书笔记(八)Loader

Loader就是一个普通的Java类加载器。

Tomcat经过实现org.apache.catalina.Loader接口来定义Loader,一个servlet容器须要制定本身的 Loader
  1. servlet容器不该该信任servlet,若是容器使用系统类加载器,那么servlet能够"看见"CLASSPATH中的class.
  2. 在加载类时能够加入特定的规则
  3. 能够换成以前加载过的类
  4. 支持自动重加载(热部署):自定制的类加载器(S)使用另一个线程一直检查servlet和它依赖的class(S负责加载的)的时间戳,当WEB-INF/classes或WEB-INF/lib目录中的类被改变时,从新加载之。只需实现org.apache.catalina.loader.Reloader接口

Java类加载器 java

jvm从java1.2开始使用3个类加载器:启动类加载器(祖父 GF)、扩展类加载器(父亲 F)、系统类加载器(儿子 S)。 apache

  1. GF:由操做系统本地代码编写,负责加载JVM启动所需的类库,还负责加载Java核心类库(如java.lang.*、java.io.*)
  2. F:负责加载在标准扩展目录中的类(/jdk/jre/lib/ext)
  3. S:加载CLASSPATH中的类.

双亲委托模式 缓存

      当JVM要加载一个类时,S首先被调用,但S不会去直接加载这个类,他会委托给F,而F会委托给GF,若是GF没有找到这个类就让F去加载,若是F也没找到,就让S去加载。若是最后S也没找到,就会抛出java.lang.ClassNotFoundException异常。 安全

双亲委托模式有效保证了类加载的安全性:
      有人恶意写了一个java.lang.String类,但愿可以替代java核心同名类,当String在程序某处被调用时,S委托F,F委托GF,GF会找到真正的Java核心库中的String类并加载,而恶意的String不会得到被加载的机会。
app

Web应用在加载servlet和其余class是要遵照规则的:
      servlet只可使用部署在WEB-INF/classes或其子目录下的class.
放在WEB-INF/lib下的jar. jvm

一个Tomcat的Loader表明的是一个Web应用加载器而不是一个类加载器.它必须实现org.apache.catalina.Loader接口.一个Loader的实现拥有一个类加载器(org.apache.catalina.loader.WebappClassLoader)并能够经过Loader接口中定义的getClassLoader方法得到它。 spa

Loader一般会和一个Context(表明一个Web应用,也是一个容器)绑定在一块儿经过Loader接口中定义的getContainer和setContainer方法,得到和设置Context.
操作系统

重加载
      若是Conext中的class被改变了,Loader(若是支持的话)会调用Context接口中定义的reload方法从新加载它们,而不须要重启Tomcat。Loader中定义了setReloadable和getReloadable来决定是否支持重加载。
      默认的org.apache.catalina.core.StandardContext是不支持重加载的,若是想要支持,咱们须要在server.xml添加一个Context元素:
      <Context path="/myApp" docBase="myApp" debug="0" reloadable="true"/>
.net

Loader接口定义
线程

public interface Loader {
    public ClassLoader getClassLoader();
    public Container getContainer();
    public void setContainer(Container container);
    public DefaultContext getDefaultContext();
    public void setDefaultContext(DefaultContext defaultContext);
    public boolean getDelegate();
    public void setDelegate(boolean delegate);
    public String getInfo();
    public boolean getReloadable();
    public void setReloadable(boolean reloadable);
    public void addPropertyChangeListener(PropertyChangeListener listener);
    public void addRepository(String repository);
    public String[] findRepositories();
    public boolean modified();
    public void removePropertyChangeListener(PropertyChangeListener listener);
}

Tomcat提供了一个Loader的实现:org.apache.catalina.loader.WebappLoader
而且提供了它的类加载器实现:org.apache.catalina.loader.WebappClassLoader(继承了java.net.URLClassLoader类)

Reloader接口

public interface Reloader {
    public void addRepository(String repository);
    public String[] findRepositories ();
    //true:支持重加载
    public boolean modified();
}
org.apache.catalina.loader.WebappLoader
  1. 建立一个类加载器
  2. 设置repositories仓库(能够理解为Loader去加载class的地方)
  3. 设置classpaht
  4. 设置权限
  5. 开启一个新线程来实现自动重加载(循环检查)

org.apache.catalina.loader.WebappClassLoader

缓存加载过的类

  1. local cache:WebappClassLoader实例本身来管理
  2. super cache:java.lang.ClassLoader管理了一个Vector(存以前加载过的类)来防止GC,由超类管理
加载类
  1. 检查local cache
  2. 检查super cache
  3. 检查repositories仓库 找到加载 找不到抛异常ClassNotFoundException
相关文章
相关标签/搜索