您的位置:首页 > 运维架构 > Tomcat

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

2013-02-22 14:30 399 查看
Loader就是一个普通的Java类加载器。

Tomcat通过实现org.apache.catalina.Loader接口来定义Loader,一个servlet容器需要制定自己的
Loader。

servlet容器不应该信任servlet,如果容器使用系统类加载器,那么servlet可以"看见"CLASSPATH中的class.

在加载类时可以加入特定的规则

可以换成之前加载过的类

支持自动重加载(热部署):自定制的类加载器(S)使用另外一个线程一直检查servlet和它依赖的class(S负责加载的)的时间戳,当WEB-INF/classes或WEB-INF/lib目录中的类被改变时,重新加载之。只需实现org.apache.catalina.loader.Reloader接口

Java类加载器

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

GF:由操作系统本地代码编写,负责加载JVM启动所需的类库,还负责加载Java核心类库(如java.lang.*、java.io.*)

F:负责加载在标准扩展目录中的类(/jdk/jre/lib/ext)

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不会获得被加载的机会。

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

一个Tomcat的Loader代表的是一个Web应用加载器而不是一个类加载器.它必须实现org.apache.catalina.Loader接口.一个Loader的实现拥有一个类加载器(org.apache.catalina.loader.WebappClassLoader)并可以通过Loader接口中定义的getClassLoader方法获得它。

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"/>

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

创建一个类加载器

设置repositories仓库(可以理解为Loader去加载class的地方)

设置classpaht

设置权限

开启一个新线程来实现自动重加载(循环检查)

org.apache.catalina.loader.WebappClassLoader

缓存加载过的类

local cache:WebappClassLoader实例自己来管理

super cache:java.lang.ClassLoader管理了一个Vector(存之前加载过的类)来防止GC,由超类管理

加载类

检查local cache

检查super cache

检查repositories仓库 找到加载 找不到抛异常ClassNotFoundException
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  tomcat