一、标准web 应用程序的载入器,tomcat 中的载入器java
- servlet 容器须要实现一个自定义的载入器
- 因为servlet 容器不能彻底信任运行的servlet 程序
- 使用系统类的载入器,则该类能够访问任何程序,包括本地虚拟机中环境变量classpath 指明的全部类,很是危险
- servlet 应该只容许载入WEB-INF/classes 目录和WEB-INF/lib 目录
- 在 Catalina 中,载入器是 org.apache.catalina.Loader 接口的实例
实现一个自定义的载入器另外一个缘由程序员
- 提供自动重载功能
- WEB-INF/classes 目录和WEB-INF/lib 目录发生变化时,从新加载这些类
- 自动重载功能 实现org.apache.catalina.loader.Reloader 接口
二、java 的类载入器web
- 每次建立类实例,先将类加载到内存中
- 会在java核心类库,以及classpath 变量中指明的目录中扫描相关类
- 找不到抛异常:ClassNotFoundException
三、JVM 三种类载入器apache
- 引导类载入器(bootstrap class loader)
- 扩展类载入器(extension class loader)
- 系统类载入器(system class loader)
- --------------三个类是父子继承关系,从上到下的顺序
引导类载入器(bootstrap class loader)bootstrap
扩展类载入器(extension class loader)数组
- 载入标准扩展类目录中的类(jdk/jre/lib/ext)
系统类载入器(system class loader)缓存
- 默认类载入器,搜索classpath指明的 路径和jar文件
类载入器代理模型tomcat
- 按照从上到下的顺序载入,优先级递减
- 主要是为了解决类载入过程当中的安全性问题
- 可使用安全管理器来限制某个类或路径的访问
- 举例:某人在硬盘上写上java.lang.Object 会被忽略,而不是覆盖系统的Object类
继承java.lang.ClassLoader 能够实现本身的类载入器安全
tomcat之因此使用自定义类载入器缘由:app
- 为了在载入类中指定某些规则
- 为了缓存已经载入的类
- 为了实现类的预载入,方便使用
四、Loader 接口
在载入web应用程序中须要servlet 类及其相关类时,须要遵照一些明确规则
- 应用程序的servlet 类只能部署在WEB-INF/classes 目录下
- servlet 类不能访问其余路径的类,即便这些类包含在当前tomcat jvm的classpath 路径下
- servlet 类只能访问 WEB-INF/lib 目录下
tomcat 载入器指的是web 应用程序载入器
- 必须实现 org.apache.catalina.Loader 接口
- 实现中会使用 org.apache.catalina.WebappClassLoader
WEB-INF/classes 和WEB-INF/lib 做为仓库被添加到载入器中的
- addRepository 添加一个仓库
- getRepository 获取全部已添加仓库数组对象
tomcat 载入器会和一个Context 级别容器关联
- Context 中一个或多个类被修改了,loader 接口支持自动重载(程序员不须要重启tomcat)
- loader 接口使用 modified方法自动重载
- 配置自动重载

载入器实现会指明,是否委托给一个父类载入器

具体实现中使用了org.apache.catalina.WebappClassLoader 继承自 java.net.URLClassLoader

五、Reloader 接口

六、WebappLoader 类
- org.apache.catalina.WebappLoader 实现了 Loader 接口
- 其实例就是web 应用程序中的载入器
- 也实现了LifeCycle 接口,其相关联的容器启动和关闭
- 实现了 RunnerAble 接口
调用WebappLoader 的start 方法,会完成如下几项重要工做:
- 建立一个类载入器
- 设置仓库
- 设置类路径
- 设置访问权限
- 启动一个新线程支持自我重载
(1)建立一个类载入器
- 私有字符串变量loaderClass 默认保存的是org.apache.catalina.WebappClassLoader
- 也能够继承WebappClassLoader,实现自定义类加载器(不继承,会抛异常)

(2)设置仓库
- 调用 setRepository 将WEB-INF/classes 目录传入类加载器addRepository
- WEB-INF/lib 目录传入类加载器 setJarPath
(3)设置类路径
(4)设置访问权限
- 启用了安全管理器,使用setPermission 设置相关目录访问权限
(5)开启新线程开启类的从新载入
- WebappLoader 使用一个线程周期性扫描资源的时间戳(时间间隔是变量checkInterval 默认15秒)
七、WebappClassLoader 类(载入器类)
该类设计考虑了优化和安全两个方案
- 缓存以前已经载入的类来提高性能(缓存加载失败的类,下次访问直接抛异常)
安全性

(1)类缓存
能够是本地缓存
- ClassLoader 维护一个Vector 对象,保存已载入的类,防止其被当垃圾回收
WebAppClassLoader 载入的类都是为资源(org.apache.catalina.ResourceEntry的实例)
该实例会保存
- class文件字节流
- 最后修改时间
- Manifest信息(若是来自 jar文件的话)

- 已缓存类会存储在一个叫resourceEntries的hashMap 中,key为载入资源名称
(2)载入类
遵照如下规则
- 因为全部类都已缓存,先检查本地缓存
- 本地缓存没有检查上一层缓存(即ClassLoader 类的 findLoadedClass 方法)
- 两者都没有使用系统类载入器载入(防止web应用程序的类覆盖javaee的类)
- 若启用了SecurityManager ,检查是否容许载入该类;若是不容许,抛出 ClassNotFoundException
- 打开delegate 标志位,或者带载入的类属于包触发器的包名,使用父载入器载入,(父为空,使用系统载入器)
- 从当前仓库中载入相关类
- 当前仓库没有,且标志位delegate 关闭,使用父载入器载入,(父为空,使用系统载入器)
- 仍未找到抛出ClassNotFoundException