tomcat 学习笔记之 载入器

一、标准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

  •  引导启动java 虚拟机

扩展类载入器(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 类(载入器类)

该类设计考虑了优化和安全两个方案

  • 缓存以前已经载入的类来提高性能(缓存加载失败的类,下次访问直接抛异常)

安全性

  • 不容许载入某些类,写入triggers 变量

  • 委托给系统类载入器

(1)类缓存

  • 为了达到更好的性能,会缓存已载入的类

能够是本地缓存

  • ClassLoader 维护一个Vector 对象,保存已载入的类,防止其被当垃圾回收

WebAppClassLoader 载入的类都是为资源(org.apache.catalina.ResourceEntry的实例)

该实例会保存

  • class文件字节流
  • 最后修改时间
  • Manifest信息(若是来自 jar文件的话)

  • 已缓存类会存储在一个叫resourceEntries的hashMap 中,key为载入资源名称

(2)载入类

遵照如下规则

  • 因为全部类都已缓存,先检查本地缓存
  • 本地缓存没有检查上一层缓存(即ClassLoader 类的 findLoadedClass 方法)
  • 两者都没有使用系统类载入器载入(防止web应用程序的类覆盖javaee的类)
  • 若启用了SecurityManager ,检查是否容许载入该类;若是不容许,抛出 ClassNotFoundException
  • 打开delegate 标志位,或者带载入的类属于包触发器的包名,使用父载入器载入,(父为空,使用系统载入器)
  • 从当前仓库中载入相关类
  • 当前仓库没有,且标志位delegate 关闭,使用父载入器载入,(父为空,使用系统载入器)
  • 仍未找到抛出ClassNotFoundException
相关文章
相关标签/搜索