第十课:

不知不觉就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的更多相关文章

  1. Tomcat从零开始(十一)WebappLoader概述

    好的,我们先看看这个WebappLoader到底在开始的时候做了什么,先看看他的start()方法. public void start() throws LifecycleException { / ...

  2. Tomcat从零开始(十七)——StandardWrapper

    第十七课:StandardWrapper 课前复习: 不知道大家是否还有印象,就是在6.7节课说的4种container,粗略的从大到小来说就是engine,host,context,和wrapper ...

  3. solr4.10.3部署到tomcat——(十)

    0. 准备环境:

  4. Linux搭建JavaEE开发环境与Tomcat——(十)

    服务器通过ip地址访问是不需要备案的,如果通过域名访问的话才需要备案. 1.安装Mysql 在CentOS7上安装MySQL时,出现了以下的提示: 原因是: CentOS7带有MariaDB而不是my ...

  5. tomcat在linux下自启动

    Linux下设置tomcat开机自启动  一.以root用户登录系统: 二.进入init.d文件夹 cd /etc/init.d/ 三.创建并打开tomcat文件 vi tomcat 四.tomcat ...

  6. 从零开始学 Java - 我放弃了 .NET ?

    这不是一篇引起战争的文章 毫无疑问,我之前是一名在微软温暖怀抱下干了近三年的 .NET 开发者,为什么要牛(sha)X一样去搞 Java 呢?因为我喜欢 iOS 阿!哈哈,开个玩笑.其实,开始学 Ja ...

  7. Eclipse的Tomcat热部署,免重启的方法

    背景与目标: 最好使用MyEclipse部署Web应用,在开发调试时,非常方式.资源文件修改可以自动的同步.修改Java文件,除非改变类的结构定义,也可以实现热部署的效果. 后来使用Eclipse J ...

  8. tomcat使用详解(week4_day2)--技术流ken

    tomcat简介 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun和其他一些公司及个人共同开发 ...

  9. linux下部署tomcat 上线jpress博客系统

    tomcat Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器. tomcat有三个端口 开始部署 安装tomcat 第一步:下载tomcat 安装包 tomcat官网 ...

随机推荐

  1. Python环境变量配置问题

    安装Python2.7后,在环境变量中加入路径方法如下: 1,设置:右键单击计算机-->属性-->高级系统设置-->环境变量-->Path-->编辑Path-->在 ...

  2. Robot Framework作者建议如何选择自动化测试框架

    本文摘自:InfoQ中文站http://www.infoq.com/cn/news/2012/06/robot-author-suggest-autotest Robot Framework作者建议如 ...

  3. Android消息机制不完全解析(下)

    接着上一篇文章Android消息机制不完全解析(上),接着看C++部分的实现. 首先,看看在/frameworks/base/core/jni/android_os_MessageQueue.cpp文 ...

  4. 关于微信的jsapi_ticket的获取方法;

    对于一个从前端转到后端的开发人员来说,这个玩意儿开始的时候是有点郁闷:不过明白原理之后就简单了, 获取jsapi_ticket:必须先获取access_token; 微信开发文档说access_tok ...

  5. 解决cookie无法删除的问题

    今天遇到一个cookie无法删除的问题,退出操作时cookie无法删除,必须在首页先进行退出操作,后来发现一个网友的博客,介绍了无法删除Cookie的原因,原来是我关于cookie的基础知识没搞清楚. ...

  6. FPGA中浮点运算实现方法——定标

    有些FPGA中是不能直接对浮点数进行操作的,仅仅能採用定点数进行数值运算.对于FPGA而言,參与数学运算的书就是16位的整型数,但假设数学运算中出现小数怎么办呢?要知道,FPGA对小数是无能为力的,一 ...

  7. 解决Android中TextView首行缩进的问题

    方式一:(推荐) setText("\u3000\u3000"+xxxxx); 方式二:这种方式不同分辨率会有问题 setText(""+xxxxx); 半角: ...

  8. 2014.8.30.ref,out,params,enum,递归

    (一)ref 函数形参变量的输入有两种方式:传值,传址.而ref则为传址.eg: static int Add(ref int n) { Console.WriteLine("Add---- ...

  9. BZOJ 1066: [SCOI2007]蜥蜴( 最大流 )

    结点容量..拆点然后随便写 --------------------------------------------------------------- #include<cstdio> ...

  10. IIS发布网站后局域网其他用户不能访问问题(转)

    如果本机能正常访问,而局域网其他用户不能访问,那么判断的结果很可能是防火墙问题. 解决方法: 既然问题出在Windows7或Windows Server 2008 R2的防火墙上,那么我们可以有以下两 ...