tomcat源码阅读之载入器(Loader)
一、Java类的载入器:
双亲委派模型:

1、JVM提供了三种类型的类加载器:引导类载入器(bootstrap class loader)、扩展类载入器(extension class loader)、应用程序类载入器(也叫系统类载入器:system class loader);
2、引导类载入器用于引导启动java虚拟机;引导类载入器使用本地代码实现,用来载入jvm需要的类,以及所有java核心类,比如java.lang和java.io等包下的类。扩展类载入器载入标准扩展目录中的类,标准扩展目录是jdk/jre/lib/ext。系统类载入器会搜索在环境变量CLASSPATH中指明的路径和JAR文件,他作为自定义载入器的父类,子类只需要覆盖一些方法就可以实现自定义载入类;
3、当需要载入一个类时,会首先调用应用程序载入器(系统类载入器),应用程序载入器会将请求交给扩展类载入器,扩展类载入器又将请求交给引导类载入器,因此引导类载入器总是会首先执行载入类的任务,如果引导类载入器找不到需要载入的类,那么扩展类载入器尝试载入该类,如果扩展类载入器也找不到这个类,就由应用程序载入器执行载入任务,如果还是找不到这个类,则抛出java.lang.ClassNotFoundException异常;
4、双亲委派模型的作用是为了安全性,比如当用户编写了一个java.lang.object的类,他可以恶意的访问磁盘中的任意目录,但是在载入时双亲委派模型会交由引导类载入器载入,,结果是引导类载入器搜索其核心库,找到标准的java.lang.Object类并载入,自定义的java.lang.Object类并没有被载入,因此恶意代码不会被执行,安全性得到保障;
自定义类加载器:
1、继承java.lang.CLassLoader类;
2、重写父类的findClass方法;
通过ClassLoader的源码可以看到,findClass方法并未有实现代码,其是交由子类来实现自定义查找类并加载,一般不建议重写loadClass方法;
二、Tomcat载入器UML图:

1、Loader接口作为tomcat的载入器,webappLoader为其实现类;createClassLoader方法会创建一个webappClassLoader类型的载入器,webappClassLoader类继承自URLClassLoader(URLClassLoader最终继承自ClassLoader类)的自定义载入器;WebappLoader的对类的加载功能实现都是由这个自定义类载入器实现的;
2、createClassLoader默认会根据loaderClass的字符串变量生成一个webappClassLoader的自定义载入器,可以通过setLoaderClass改变loaderClass的值来指定自定义的类加载器,但是这个自定义的类加载必须从WebappClassLoader派生过来;
3、WebappLoader的run方法运行在一个线程中,每隔checkInterval秒的时间就扫描一次路径下的文件(checkInterval默认是15秒,可以改变),如果有文件发生改变了,则创建一个新的线程,在线程中调用Context.reload方法重新加载类(首先调用notifyContext生成一个WebappContextNotifier线程,然后在这个线程中调用Context.reload方法重新加载类);
4、webappClassLoader实现了reloader接口来实现类的自动重载,这个接口中最重要的方法modified,如果web应用程序中的某个servlet被修改了,modified会返回true,然后扫描线程会通知Context重新载入servlet类;
StandardContext默认是不支持自动重载servlet类的,要想开启这个功能,需要在server.xml文件中配置下面这样一行:
<Context path="/myApp" docBase="myApp" debug="0" reloadable="true"/>
5、WebappClassLoader作为一个自定义类载入器,考虑了优化和安全两方面,比如在resourceEntries中缓存以及功能载入过的类,在notFoundResources中缓存加载失败的类的名字,这样当再次加载同一个类,如果在resourceEntries中则直接返回,如果在notFoundResources中则直接抛出ClassNotFoundException异常;
缓存类资源的类是ResourceEntry,其中loadedClass存储了类的字节流,lastModified存储了最后一次修改时间;
6、基于安全性的考虑,WebappClassLoader不允许加载指定的类和包,代码如下:


7、WebappClassLoader.loadClass载入类时的流程:
a) 首先检查本地缓存,如果则直接返回;
b) 如果本地缓存没有,则检查上一层缓存,即调用java.lang.ClassLoader.findLoadedClass;
c) 若两个缓存都没有,则使用系统的类载入器加载;
d) 若启用了SecurityManager,则检查是否允许载入该类,如果是禁止的,则抛出ClassNotFoundException异常;
e) 如果标志位delefate打开,则调用父类载入器来载入,如果父类载入器为空,则使用系统类载入器载入;
f) 从当前仓库中载入相关类;
g) 如果当前仓库也没有,且delegate关闭,则使用父类载入器来载入,如果父类载入器为空,则使用系统类载入器载入;
h) 此时若仍未找到需要的类,则抛出ClassNotFoundException异常;
tomcat源码阅读之载入器(Loader)的更多相关文章
- tomcat源码阅读之部署器
我们知道web应用是用Context实例表示的,而Context是部署到Host实例中的,因此tomcat的部署器是关联的Host实例.Context实例可以用WAR文件部署,也可以把整个web应用的 ...
- SpringMVC源码阅读:拦截器
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- Tomcat源码阅读(二)初始化
近来,我开始阅读tomcat的源码,感觉还挺清晰易懂:为了方便理解,我参考了网上的一些文章,把tomcat的组成归纳一下:整个tomcat的组成如下图所示: Tomcat在接收到用户请求时,将会通过以 ...
- tomcat源码阅读
1 工具准备 需要SVN.Maven.JDK.Eclipse.Eclipse M2插件 2 下载源码及发布包 源码在这里:http://svn.apache.org/repos/a ...
- tomcat源码阅读之Catalina和Bootstrap解析
一.Cataling类分析: 1.Catalina类是启动类,用于启动或者关闭Server对象,它包含一个Digester对象,用于解析tomcat配置文件:conf/server.xml;调用pro ...
- tomcat源码阅读之过滤器
一.Servlet过滤器: 1.介绍: Servlet过滤器本身并不生成请求和响应对象,它只提供过滤作用. Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request ...
- tomcat源码阅读之SingleThreadModel
一.接口简介: 实现了SingleThreadModel接口的servlet类只能保证在同一时刻,只有一个线程执行该servlet实例的service方法,在tomcat实现中会创建多个servlet ...
- tomcat源码阅读之session管理器(Manager)
一.UML图分析: (一) Session: Session保存了一个客户端访问服务器时,服务器专门为这个客户端建立一个session用来保存相关的会话信息,session有一个有效时间,这个时间默认 ...
- tomcat源码阅读之BackupManager
一. 配置: <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOpti ...
随机推荐
- Leetcode 92
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...
- js数组的方法小结
js中数组是一种非常常用数据结构,而且很容易模拟其他的一些数据结构,比如栈和队列.数组的原型Array.prototype内置了很多方法,下面就来小小总结一下这些方法. 检测数组就不用多说了,使用EC ...
- js判断数组,对象是否存在某一未知元素
1.对象 var obj = { aa:'1111', bb:'2222', cc: '3333' }; var str='aa'; if(str in obj){ console.log(obj[s ...
- java并发编程:线程安全管理类--原子操作类--AtomicLongArray
1.类 AtomicLongArray public class AtomicLongArray extends Object implements Serializable 可以用原子方式更新其元素 ...
- Our supersheet
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- delphi中使用MSWINSCK.OCX控件
1.首先是把winsck控件导入到delphi中,就是导入一个ActiveX控件,步骤略过. 2.将导入的winsck控件拖入你的Form中. 3.对winsck进行基本设置(IP,Port). 4. ...
- 设置MyEclipse字体大小
设置MyEclipse字体大小
- 、搭建Android开发环境
一.搭建Android开发环境 准备工作:下载Eclipse.JDK.Android SDK.ADT插件 下载地址:Eclipse:http://www.eclipse.org/downloads/ ...
- QLabel 内容长度超过控件本身长度时超出的部分用省略号
void JunEditableLabel::setText(const QString &string) { QFont font("Tahoma"); font.set ...
- PyCharm Debug调试程序
步骤一:在代码区要进行调试的代码行左侧单击鼠标左键,添加调试断点符号 步骤二:右键单击源文件或代码区内部,弹出菜单,选择[Debug ***] 或在右上角工具栏区单击[debug]按钮,快捷键[shi ...