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 ...
随机推荐
- forget word out a~4
1● ana 错误,分开 2● ante 先,前面 3● anti 反对,相反 1◆ ana 2◆ ante 3◆ anti 1● dem(o) 2● pupl 3● ...
- 从用户输入url到页面最后呈现 发生了些什么?
一.浏览器获取资源的过程: 1.输入url 2.浏览器解析url,获得主机名 3.将主机名转换成服务器ip地址(查找本地DNS缓存列表,如果没有则向默认的DNS服务器发送查询请求) 4.浏览器建立一条 ...
- Hive时间函数笔记
unix_timestamp()函数: 返回值: bigint说明: 获得当前时区的UNIX时间戳 举例: hive> select unix_timestamp() from dual; 14 ...
- Nexcel的行列,和单元格坐标
book.Sheets[1].UsedRange.Rows.Count 行数从1开始 book.Sheets[1].UsedRange.LastCol 从0开始 book.Sheets[1].Cell ...
- python--ConfigParser读写改配置文件
from configparser import ConfigParser fp = 'conf.ini' #定义配置文件名 conf = ConfigParser() #实例化 conf.read( ...
- 中断一个telnet连接
假如我要telnet一个端口通不通,测试通过之后后出现黑屏的界面 这时候需要按下ctrl+] 组合键 然后输入 quit 即可退出telnet窗口,可以继续测试下一个端口~
- SharePoint 数据库管理-PowerShell
1. 显示所有SharePoint数据库 Get-SPDatabase –ServerInstance "SP2010\SQLSharePoint" 2. 获取指定的数据库 $da ...
- 一种简单的hook方法--LD_PRELOAD变量
LD_PRELOAD这个变量允许你定义在程序运行时优先加载的动态链接库,从而在程序运行时的动态链接 下面程序的看一个例子-getuid.c //getuid.c #include<stdio.h ...
- bga
本文记录在bga布线的难题. 1一开始就要预留好布线局域. 最近出现布线太密,修改时就麻烦了. http://bbs.elecfans.com/jishu_521995_1_1.html
- 获取当前进程目录 GetCurrentDirectory() 及 获取当前运行模块路径名GetModuleFileName()
GetCurrentDirectory 获得的是当前进程的活动目录(资源管理器决定的),可以用SetCurrentDirectory 修改的. 转自 http://m.blog.csdn.net/bl ...