Tomcat从零开始(十)Loader
第十课:
不知不觉就10篇blog了,说实话,我是第一次更这么长时间的Blog。
嗯,今天说说Loader,在以前的课程中,也就是内个能使用最初级的servlet的那一节,我们使用了URLClassLoader加载Servlet,但是这是不科学的,因为如果用系统自带的Loader加载,servlet能访问类库太多就太不安全了。所以我们需要实现自己的一个加载器,那我们首先看看Java的Loader。
JVM在运行的时候,会产生3个classLoader,分别是Boostrap,ClassLoader,Extension Classloader、AppClassLoader。
首先第一个Bootstrap,根据他的意思就知道是启动用的,它是用C++编写的,而且实际上不是classLoader的子类,而是JVM自身实现的。在JVM源码中,我们可以看到用static const char classpathFormat [] 数组来存储 所需加载的jar之后就是extension classLoader这个类了,他是负责加载/lib/ext这个文件夹下的类的,或者java.ext.dirs这个系统属性指定(别说不知道是什么,我们在以前的课程中,经常使用的user.dir也是系统属性),因为默认的Ext.dirs对所有从同一个JRE中启动的JVM都是通用的,所以放入这个目录的JAR类包对所有的JVM和system classloader都是可见的。剩下的一个就是AppClassLoader了,我们用的url内个也是它的儿子,用来加载classpath。ClassLoader加载类用的是靠上级的方式(这个名字有点忘了 AppClassLoader->ExtClassLoader->好像是全局委托吧),就是加载类的时候,上级先找,找不到下级来。所以就是 bootstrap。我们需要思考一下为什么要采用这种模式来处理,因为如果我们编写一个具有危险性的类,注意这个类要和系统存在的类重名,比如java.lang.math,那么当加载的时候这个有危险的类就不会加载到用户,因为bootstrap就不会加载这个类,因为那时候已经有原有的java.lang.Math了。如果不采用,那就直接在用户机器上运行,破坏安全。
这里举一个例子,比如你有两个类,一个放到了ext.dirs中 这个类引用了另外一个类,另外一个放到classpath中,那么 就会报错了。因为第二个类默认用Extloader来搜索,他不会让appLoader去查找。
妥了,那现在说说Tomcat为什么要使用自己的加载器,一个原因在上面已经说了,另外就是需要缓存以前的类,和预先加载一些类做预备。当然,说这么多J2SE的loader是为了让大家不与tomcat的loader混淆, j2se是用来加载类的,而tomcat实际上是一个webApp的Loader,Loader组件必须要实现org.apache.catalina.Loader接口。
Tomcat的Loader其实也是像J2SE中那样的。
首先是Commonclass Loader,主要是加载tomcat 的common下的所有jar和类。他的上级是appclassloader
之后就是server和shared Class Loader,两只个的区别是,前者是加载tomcat的核心类,主要是tomcat的server目录。而后者是加载 web app的类(公共类)。他们的上级是common class loader
再之后就是 webappclass loader了,这个是用来加载每个app的WEB-INF/ classes和lib的。他的上级是shared class loader。但是它的加载 和 之前的不一样,刚才说了Tomcat的loader是有缓存的,如果之前的类没加载,那么就给它 上级来加载(这里就是j2se的加载了),之后,如果加载失败了,那就查找WEB-INF/classes 和 lib下,这个是怎么实现的,我下面就会说。如果再没找到,就给shared class loader。 如果以前加载过,直接从缓存取就行了。
其实这里没什么说的,其实主要理解一下Java的loader 的委托模式。
我们先来看看Loader这个接口,其中我们注意与Repository有关的方法,Repository这个单词的意思是仓库。那么思考一下,这里的repository就是代表类库的意思,add就是添加,find就是查找。那么,我们来看看
Loader的实现类,是如何实现的。这个类在org.apache.catalina.loader.WebappLoader中。
public void addRepository(String repository) { if (debug >= 1)
log(sm.getString("webappLoader.addRepository", repository)); for (int i = 0; i < repositories.length; i++) {
if (repository.equals(repositories[i]))
return;
}
String results[] = new String[repositories.length + 1];
for (int i = 0; i < repositories.length; i++)
results[i] = repositories[i];
results[repositories.length] = repository;
repositories = results; if (started && (classLoader != null)) {
classLoader.addRepository(repository);
setClassPath();
}
//我们可以看到,这里就是一个数组的操作
}
之后我们看看他的Start()方法,这个方法在Lifecycle中说过了。那么,在运行的初期,系统就会默认调用一个方法setRepositories(),这个在start()方法可以自己找到,那我贴一段setRepositories方法。
// 加载Context的工作目录
File workDir =
(File) servletContext.getAttribute(Globals.WORK_DIR_ATTR);
if (workDir == null)
return;
log(sm.getString("webappLoader.deploy", workDir.getAbsolutePath())); DirContext resources = container.getResources(); //这里,就是将这个 classes目录设置到repository中,所以不用看了,我们的apploader
//一定默认加载了 /WEB-INF/classes目录的实现。
String classesPath = "/WEB-INF/classes";
DirContext classes = null;
看到了么,这里就是默认加载classes的地方,其实/lib目录也是开始的时候就被加到repositories中了,这个希望可以自己找到。毕竟读代码也是需要多多练习的~。
我们都知道,这个东西是要跟一个容器关联的,Engine,host,Context,Wrapper这四个容器中,他关联的是context。也不是说必须关联,只是context必须要有这个加载器。另外,我们在用tomcat的时候,会发现另外一个功能,就是当我们更改完servlet之后一般都不需要重启服务器,因为tomcat存在一种reloader机制。这个reloader也是一个接口,每个加载器都必须实现这个,其实就是实现以下reloader接口的 modified方法,来看 是否被更改,更改了就重新加载。
今天先说这么多,明天我会具体的分析一下这个appclassloader这个类。其实我觉得讲了这么多了,这个类其实大家也都能看懂了吧。另外说一下,用下面这段代码,可以看bootstrap在启动的时候到底加载了什么jar。注意! 这里不能用Eclipse去用这段代码。因为eclipse的Access Rule的问题。具体的设置,我会在下面贴图。
public class Test {
public static void main(String args[]){
URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls[i].toString());
} }
}
首先看一下运行截图。
Tomcat从零开始(十)Loader的更多相关文章
- Tomcat从零开始(十一)WebappLoader概述
好的,我们先看看这个WebappLoader到底在开始的时候做了什么,先看看他的start()方法. public void start() throws LifecycleException { / ...
- Tomcat从零开始(十七)——StandardWrapper
第十七课:StandardWrapper 课前复习: 不知道大家是否还有印象,就是在6.7节课说的4种container,粗略的从大到小来说就是engine,host,context,和wrapper ...
- solr4.10.3部署到tomcat——(十)
0. 准备环境:
- Linux搭建JavaEE开发环境与Tomcat——(十)
服务器通过ip地址访问是不需要备案的,如果通过域名访问的话才需要备案. 1.安装Mysql 在CentOS7上安装MySQL时,出现了以下的提示: 原因是: CentOS7带有MariaDB而不是my ...
- tomcat在linux下自启动
Linux下设置tomcat开机自启动 一.以root用户登录系统: 二.进入init.d文件夹 cd /etc/init.d/ 三.创建并打开tomcat文件 vi tomcat 四.tomcat ...
- 从零开始学 Java - 我放弃了 .NET ?
这不是一篇引起战争的文章 毫无疑问,我之前是一名在微软温暖怀抱下干了近三年的 .NET 开发者,为什么要牛(sha)X一样去搞 Java 呢?因为我喜欢 iOS 阿!哈哈,开个玩笑.其实,开始学 Ja ...
- Eclipse的Tomcat热部署,免重启的方法
背景与目标: 最好使用MyEclipse部署Web应用,在开发调试时,非常方式.资源文件修改可以自动的同步.修改Java文件,除非改变类的结构定义,也可以实现热部署的效果. 后来使用Eclipse J ...
- tomcat使用详解(week4_day2)--技术流ken
tomcat简介 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun和其他一些公司及个人共同开发 ...
- linux下部署tomcat 上线jpress博客系统
tomcat Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器. tomcat有三个端口 开始部署 安装tomcat 第一步:下载tomcat 安装包 tomcat官网 ...
随机推荐
- C#access数据库操作
比较凌乱,有时间在整理吧. Provider=Microsoft.Jet.OLEDB.!" private void GetCon() { string strConnection=&quo ...
- Python环境变量配置问题
安装Python2.7后,在环境变量中加入路径方法如下: 1,设置:右键单击计算机-->属性-->高级系统设置-->环境变量-->Path-->编辑Path-->在 ...
- Linux内核中的list用法和实现分析
这些天在思考知识体系的完整性,发现总是对消息队列的实现不满意,索性看看内核里面的链表实现形式,这篇文章就当做是学习的i笔记吧.. 内核代码中有很多的地方使用了list,而这个list的用法又跟我们平时 ...
- myeclipse 环境配置优化,不断跟新整理中
myeclipse 环境配置,不断跟新整理中1.General --->Workspace ---> UTF-8 工作环境编码2.General --->Editors --> ...
- C#实现邮件发送功能
发送邮件所用的核心知识点 微软封装好的MailMessage类:主要处理发送邮件的内容(如:收发人地址.标题.主体.图片等等) 微软封装好的SmtpClient类:主要处理用smtp方式发送此邮件的配 ...
- Win7下qt5.3.1+opencv2.4.9编译环境的搭建(好多 Opencv2.4.9源码分析的博客)
到官网下载qt-opensource-windows-x86-mingw482_opengl-5.3.1.exe文件,执行该文件,选择默认安装即可实现QT的安装(安装在C盘的根目录下),该文件封装 ...
- logrotate 清理tomcat日志
rsyslog tomcat 服务器: 192.168.32.215 input(type="imfile" File="/usr/local/apache-tomcat ...
- 获取考试成绩的sql语句
as score,t_answer.id,t_answer.exams_name,t_answers.answer_id,t_answers.questions_id,t_answers.questi ...
- NOI2011 Day1
NOI2011 Day1 兔农 题目描述:\(fib[1]=fib[2]=1, fib[i]=fib[i-2]+fib[i-1] (i\geq 3)\),若\(fib[i] \equiv 1(mod ...
- HDU 5716 带可选字符的多字符串匹配(ShiftAnd)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5716 [题目大意] 给出一个字符串,找出其中所有的符合特定模式的子串位置,符合特定模式是指,该子串 ...