how tomcat works 读书笔记 八 载入器下
载入类
我们看看之前的文章,这一节就从SimpleWrapper的loadServlet讲起。
SimpleWrapper.java如下(省略了try catch及其他部分代码)
public Servlet loadServlet() throws ServletException {
...
String actualClass = servletClass;
Loader loader = getLoader();
// Acquire an instance of the class loader to be used
if (loader==null) {
throw new ServletException("No loader.");
}
ClassLoader classLoader = loader.getClassLoader();
if (classLoader!=null) {
classClass = classLoader.loadClass(actualClass);
// Instantiate and initialize an instance of the servlet class itself
servlet = (Servlet) classClass.newInstance();
// Call the initialization method of this servlet
servlet.init(null);
return servlet;
}
我们知道loader.getClassLoader();返回的就是webappclassloader类
看了,关键的地方就是classLoader.loadClass(actualClass);
classLoader.loadClass(actualClass)最终调用的是如下的方法,resolve为false;
下面的方法很长 但总而言之 也就以下几步
· 所有加载过的类都要进行缓存,所以首先需要检查本地缓存。
· 如果无法再本地缓存找到类,使用 java.langClassLoader 类的 findLoaderClass 方法在缓存查找类、
· 如果在两个缓存中都无法找到该类,使用系统的类加载器避免从 J2EE 类中覆盖来的 web 应用程序。
· 如果使用了安全管理器,检查该类是否允许加载,如果该类不允许加载,则抛出 ClassNotFoundException 异常。
· 如果要加载的类使用了委派标志或者该类属于 trigger 包中,使用父加载器来加载类,如果父加载器为 null,使用系统加载器加载。
· 从当前的源中加载类
· 如果在当前的源中找不到该类并且没有使用委派标志,使用父类加载器。如果父类加载器为 null,使用系统加载器
· 如果该类仍然找不到,抛出 ClassNotFoundException 异常
public Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
if (debug >= 2)
log("loadClass(" + name + ", " + resolve + ")");
Class<?> clazz = null;
// Don't load classes if class loader is stopped
if (!started) { //若webappclassloader没有启动....
log("Lifecycle error : CL stopped");
throw new ClassNotFoundException(name);
}
// (0) Check our previously loaded local class cache
clazz = findLoadedClass0(name); //看下面临时放进来的代码 等于是先在本地存储的已加载的类(hashmap)中找
if (clazz != null) {
if (debug >= 3)
log(" Returning class from cache");
if (resolve)
resolveClass(clazz);
return (clazz);
}
/*
protected Class<?> findLoadedClass0(String name) {
ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
if (entry != null) {
return entry.loadedClass;
}
return (null);
}
*/
// (0.1) Check our previously loaded class cache
clazz = findLoadedClass(name); //再去虚拟机中去找
if (clazz != null) {
if (debug >= 3)
log(" Returning class from cache");
if (resolve)
resolveClass(clazz);
return (clazz);
}
// (0.2) Try loading the class with the system class loader, to prevent
// the webapp from overriding J2SE classes
try {
//system 为系统类加载器 sun.misc.Launcher$AppClassLoader
//先用系统加载器加载
//为什么先用系统加载器 如果你写了一个类 全名为"java.lang.Object" 懂了吧?
//大家可能会想 系统加载器不是什么都能加载吗? 那还要后面的代码做什么?
//系统加载器的加载目录是什么 大家看看就明白了
clazz = system.loadClass(name);
if (clazz != null) {
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
// Ignore
}
//关于安全的问题 我没有研究过里面具体的代码
// (0.5) Permission to access this class when using a SecurityManager
if (securityManager != null) {
int i = name.lastIndexOf('.');
if (i >= 0) {
try {
securityManager.checkPackageAccess(name.substring(0,i));
} catch (SecurityException se) {
String error = "Security Violation, attempt to use " +
"Restricted Class: " + name;
System.out.println(error);
se.printStackTrace();
log(error);
throw new ClassNotFoundException(error);
}
}
}
//delegate默认为false
//filter 如果要加载的类是packageTrigers里面所限定的 就返回true
//书上说packageTrigers 里面的包是不允许载入的
//可代码里没有体现不能加载呀? 谁知道为什么,麻烦告知我一声
//另外 就像前面几章http://localhost:8080/Primitive请求的PrimitiveServlet
// delegate为false, filter(name)也是false
boolean delegateLoad = delegate || filter(name);
System.out.println(delegate+" "+filter(name)+" ddd");
// (1) Delegate to our parent if requested
if (delegateLoad) {
if (debug >= 3)
log(" Delegating to parent classloader");
ClassLoader loader = parent;
System.out.println(loader+" loader");
if (loader == null)
loader = system;
try {
clazz = loader.loadClass(name);
if (clazz != null) {
if (debug >= 3)
log(" Loading class from parent");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
// (2) Search local repositories
//至于repositories属性 是在webappLoader类start方法里 setRepositories()设定的
//使用的各个方法如下
//findClass findClassInternal findResourceInternal
//在findResourceInternal中先加载WEB-INF/classes中的文件,然后加载WEB-INF/lib下的jar文件
//最后 resourceEntries.put(name, entry);
//会把加载的enety放入resourceEntries中缓存起来
if (debug >= 3)
log(" Searching local repositories");
try {
clazz = findClass(name);
if (clazz != null) {
if (debug >= 3)
log(" Loading class from local repository");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
//系统加载器前面已经加载过来 如果程序能运行到这里就说明系统加载器不行 为什么还要再加载一遍
// (3) Delegate to parent unconditionally
if (!delegateLoad) {
if (debug >= 3)
log(" Delegating to parent classloader");
ClassLoader loader = parent;
if (loader == null)
loader = system;
try {
clazz = loader.loadClass(name);
if (clazz != null) {
if (debug >= 3)
log(" Loading class from parent");
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
// This class was not found
throw new ClassNotFoundException(name);
}
应用程序
在上一节我们已经说过,为了实现在文件变动后容器自动重载,需要在server.xml中配置
<Context path="/myApp" docBase="myApp"/>
现在我们还没有这个配置文件,替代的,在启动程序中添加如下代码:
Context context = new StandardContext();
// StandardContext's start method adds a default mapper
context.setPath("/myApp");
context.setDocBase("myApp");
如果上面的代码在eclipse中运行,项目根目录下回产生一个myApp文件夹和work文件夹
在myApp文件夹中在设置WEB-INF/classes文件夹 里面放置前几篇博客中使用的两个servlet的class文件
另外要说明一点,自动重载的方法其实就是比照最后修改时间,详细代码大家看源码即可。
how tomcat works 读书笔记 八 载入器下的更多相关文章
- How Tomcat Works 读书笔记 八 载入器 上
Java的类载入器 详细资料见 http://blog.csdn.net/dlf123321/article/details/39957175 http://blog.csdn.net/dlf1233 ...
- How Tomcat Works 读书笔记 八 加载器 上
Java的类加载器 具体资料见 http://blog.csdn.net/dlf123321/article/details/39957175 http://blog.csdn.net/dlf1233 ...
- How tomcat works 读书笔记十二 StandardContext 下
对重载的支持 tomcat里容器对重载功能的支持是依靠Load的(在目前就是WebLoader).当在绑定载入器的容器时 public void setContainer(Container cont ...
- how tomcat works 读书笔记(二)----------一个简单的servlet容器
app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...
- how tomcat works 读书笔记四 tomcat的默认连接器
事实上在第三章,就已经有了连接器的样子了,只是那仅仅是一个学习工具,在这一章我们会開始分析tomcat4里面的默认连接器. 连接器 Tomcat连接器必须满足下面几个要求 1 实现org.apache ...
- How tomcat works 读书笔记十二 StandardContext 上
在tomcat4中,StandardContext.java是最大的一个类,有117k.废话不说,开始分析吧. 其实要分析StandardContext,也就主要分析两个方法,一个start,一个in ...
- how tomcat works 读书笔记 十一 StandWrapper 上
方法调用序列 下图展示了方法调用的协作图: 这个是前面第五章里,我画的图: 我们再回顾一下自从连接器里 connector.getContainer().invoke(request, resp ...
- How tomcat works 读书笔记十七 启动tomcat 上
一路跋山涉水,这是最后一章了. 关于tomcat的启动,有两个类,一个是Catalina类,一个是Bootstrap类. 理论上,两个类可以和到一起,但是为了支持多种运行模式,又把他们分开了. 为了让 ...
- How tomcat works 读书笔记十五 Digester库 下
在这一节里我们说说ContextConfig这个类. 这个类在很早的时候我们就已经使用了(之前那个叫SimpleContextConfig),但是在之前它干的事情都很简单,就是吧context里的co ...
随机推荐
- Android倒计时器——CountDownTimer
Android倒计时器--CountDownTimer 说明 第一个参数是倒计时的时间 第二个参数是多长时间执行一次回调 /** * @param millisInFuture The number ...
- UNIX网络编程——UNIX域套接字编程和socketpair 函数
一.UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket.虽然网络soc ...
- 【OpenGL】理解一些基本问题
写在前面 啦啦啦,搞了很久的Unity Shaders,越学越觉得基础知识很重要.学Unity Shader的时候,总会想,shader到底是什么呢?shader的pipeline是什么呢?它们是怎么 ...
- (NO.00004)iOS实现打砖块游戏(十六):导弹发射道具的实现(下)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 上一篇我们完成了导弹道具相关的道具制作,本篇中我们来完成其实现 ...
- JAVA之旅(二十八)——File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤
JAVA之旅(二十八)--File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤 我们可以继续了,今天说下File 一.File概述 文件的操作是非常 ...
- 学习笔记6-Android查看应用输出的错误信息 如何部署应用到真实手机 发布软件
查看应用输出的错误信息 1. 通过LogCat窗口查看信息 右上角图标可以筛选不同级别的信息(比如info等). 右上角的+可以进行信息筛选 把应用部署到真实手机 1. 要把手机的 ...
- (九十四)集成PKRevealController实现左右抽屉视图
使用PKRevealController可以实现类似于QQ等软件的左右抽屉视图,拖出的视图分为leftView和rightView,分别取自View的左半部分和右半部分,因此,根据不同的需求,可以选择 ...
- (NO.00004)iOS实现打砖块游戏(六):反弹棒类
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 打砖块游戏另一个要素是反弹棒,我们在这篇类来实现反弹棒类. 创建 ...
- iOS中 常用的mac终端指令汇总 技术分享
通常情况下,只有高端用户才会经常用到终端应用.这并不意味着命令行非常难学,有的时候命令行可以轻松.快速的解决问题.相信所有Mac用户都尝试过命令行,今天为大家带来9个非常实用的命令行操作.一些命令行需 ...
- C++ Primer 有感(标准库vector及迭代器)
vector是同一种对象的集合,每个对象都有一个对应的整数索引值.和string对象一样,标准库将负责管理与存储元素相关的类存.引入头文件 #include<vector> 1.vecto ...