从零开始手写Tomcat的教程8节----加载器
从零开始手写Tomcat的教程8节----加载器
我首先提出几个问题,大家先思考一下,如果都可以想出来,说明对类加载器的掌握程度还算不错:
- servlet只能访问指定目录下的类,类加载器如何实现这种隔离访问机制的呢?
- 类加载器如何实现在项目不重启的情况下,对某个发生变化的类进行热更新呢?
Java的类加载器
对classpath不了解的可以看一下这篇文章----Java中令人困惑的classpath和jar到底是什么鬼?
看到这里,提问: 为什么要执行这样一个循环呢?
当然,不是直接委托给父类加载器,而是先判断该类型是否已经被当前类加载器所加载,如果没有再委托给父类加载器,即一个类只能被同一个类加载器加载一次,但是可以被多个不同的类加载器加载多次,这也引出一个没说的知识点: 类加载器+class对象才能唯一确定一个类
这里类加载器指的是两种情况: 两个类加载器本身class类型都不同; 同一个类加载器的两个实例对象加载出来的类,也被视为不同的类
更多类加载器知识点,可以看一下我之前写过关于类加载器的文章:
JVM第六卷—类加载机制
JVM第八卷—类加载与执行子系统的案例与实战
类加载器如何实现类隔离
解答一: servlet只能访问指定目录下的类,类加载器如何实现这种隔离访问机制的呢?
这里先给出一个解决思路,然后下面我们在来看一下tomcat是如何进行处理的
这里只是给我一个思路方向,这不等于tomcat选择的解决办法
解决二: 类加载器如何实现在项目不重启的情况下,对某个发生变化的类进行热更新呢?
这里类重载技术没那么简单,本节先不讲,感兴趣的,可以等几天,等到12节左右,才会进行类自动重载技术的讲解
Loader接口
WebAppLoader类
创建类加载器
设置仓库
tomcat自定义类加载器会去这些仓库下面寻找需要的servelt类
设置类路径
设置访问权限
这里说的安全管理器指的是java中的SecurityManager,感兴趣的小伙伴可以去了解一下,主要是处理权限管理的,比如对某个文件,资源是否有读写权限等
开启新线程执行类的重新载入
因为检查每个资源是否改动,以及重新加载的过程耗时可能会比较长,并且该过程与当前线程能否继续运行也没有之间关联,因此单开一个线程处理这种事情,是明智的选择
因为这样做对性能会有损耗,因此默认自动重载功能是关闭的。
WebappClassLoader类
类缓存
这样说明了在JVM中提到的方法区进行垃圾回收时执行类卸载动作时,一定要求当前类的class和实例对象不被引用,并且当前类的加载器也不被引用的前提下,该类型才会被卸载。
载入类
delegate的中文是委托的意思,放在这里很合适,表示是否将加载当前类的职责委托给父类加载器完成
应用程序
对StandardContext的分析放在12节进行。
这里我们只需要了解StandardContext类是如何与监听他触发事件的监听器协同工作的,监听器必须实现LifecycleListener接口,并调用StandardContext类的setConfigured()方法。
对于本章应用程序来说,监听器是SimpleContextConfig实例。
public class SimpleContextConfig implements LifecycleListener{
public void lifecycleEvent(LifecycleEvent event)
{
if(Lifecycle.START_EVENT.equals(event.getType()))
{
Context context=(Context)event.getLifecycle();
context.setConfigured(true);
}
}
}
这里还需要做的就是实例化StandardContext和SimpleContextConfig类,然后调用Lifecycle的addLifecycleListener()方法,通过StandardContext注册SimpleContextConfig.
这里使用PrimitiveServlet类和ModernServlet类进行测试,但是使用了StandardContext类的实例作为Servlet容器,所以servlet类只能放在应用程序目录的WEB-INF/classes目录下。
应用程序目录名称为myApp,其次还需要通知StandardContext实例到哪里查找应用程序目录,需要设置一个"catalina.base"的系统属性,其值为"user.dir"属性的值,如下所示:
System.setProperty("catalina.base",System.getProperty("user.dir"));
事实上,上面代码就是BootStrap类的main方法的第一行代码,然后实例化默认连接器:
Connector connector=new Connector();
然后,与之前章节中应用程序一样,它为两个servlet类创建两个Wrapper实例。
Wrapper wrapper1=new Wrapper();
wrapper1.setName("Primitive");
wrapper1.setServletClass("PrimitiveServlet");
Wrapper wrapper2=new Wrapper();
wrapper2.setName("Modern");
wrapper2.setServletClass("ModernServlet");
上面docBase指定的是相对路径,因此会根据应用程序的目录而发生改变,如果指定绝对路径,则不会改变,但是一般都是相对路径
总结
本小节到此基本就结束了,现在让我们再来回顾一下开头提出的问题,这里只回答第一个问题,第二个问题会在12小节进行回答:
servlet只能访问指定目录下的类,类加载器如何实现这种隔离访问机制的呢?
相关文章
- 在系统下文件上传报错:The temporary upload location [/tmp/tomcat.xxx/work/Tomcat/localhost/ROOT] is not valid
- SpringBoot应用部署到Tomcat中无法启动问题
- Tomcat服务器搭建
- CentOS安装Tomcat
- Tomcat详解(三)——tomcat多实例
- Tomcat详解(一)——tomcat基础知识
- 从零开始手写Tomcat的教程13节---Host和Engine
- 从零开始手写Tomcat的教程11节----StandardWrapper
- 从零开始手写Tomcat的教程5节---servlet容器
- Atitit webserver tomcat 7 8.0 8.5 9.0新特性 Tomcat 7 的七大新特性 - 编程语言 - ITeye资讯.html tomcat 8.0特性 - CSD
- tomcat中jsp引用图片img的src属性带中文路径无法显示的解决
- #化鲲为鹏,我有话说# 鲲鹏弹性云服务器配置 Tomcat
- eclipse tomcat add时提示The Tomcat server configuration at ServersTomcat v6.0 Server at localhost-
- 服务器tomcat配置教程
- Tomcat服务器的默认端口是多少?怎样修改tomcat的端口?
- tomcat 测试页面显示
- Tomcat安装及配置教程
- 从零开始手写Tomcat的教程14节----服务器组件(Server)和服务组件(Service)
- 从零开始手写Tomcat的教程9节---Session管理
- 从零开始手写Tomcat的教程5节---servlet容器
- 从零开始手写Tomcat的教程4节---Tomcat默认连接器
- 【安装包】apache-tomcat-8.5.45-windows-x64
- Tomcat(三):日志
- tomcat Context容器(中):Tomcat如何隔离Web应用?
- Tomcat 简介与安装