《深入剖析学习.pptx》由会员分享,可在线阅读,更多相关《深入剖析学习.pptx(29页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、第八章 载入器*web应用程序载入器,即Tomcat中的载入器。*servlet容器需要实现一个自定义的载入器,而不能使用简单的系统的类载入器,因为:(1)servlet容器不应该完全相信它正在运行的servlet类,如果使用系统的类载入器,那么servlet就能够访问到所有的类,包括JVM中CLASSPATH指明的路径下的所有类和库,安全性低。(2)可以提供自动重载功能,当可以使用的目录下的类发生变化时,Web应用程序会重新载入这些类。第1页/共29页第八章 载入器*在Catalina中,载入器是 org.apache.catalina.Loader接口的实现*支持自动重载,载入器须实现 o
2、rg.apache.catalina.loader.Reloader 接口*了解两个术语:仓库(repository)和资源(resource)仓库:表示类载入器会在哪里搜索要载入的类 资源:指的是一个类载入器中的DirContext对象第2页/共29页第八章 载入器Java的类载入器 从J2SE 1.2 开始,JVM使用了三种类载入器来载入所需要的类。引导类载入器-引导启动JVM-载入Java核心类-依赖JVM和操作系统版本 扩展类载入器-载入标准扩展目录中的类-依赖于JDK供应商的具体实现 系统类载入器-默认的载入器,搜索CLASSPATH中指明的路径和JVR文件第3页/共29页第八章 载
3、入器JVM如何选择类载入器?-代理模型(1)首先,调用系统类载入器,它将任务交给其父载入器(2)扩展类载入器又将任务交给其父载入器(3)引导类载入器首先执行载入某个类的任务,如果找不到需要载入的类,那么扩展类载入器尝试载入该类。(4)如果扩展类载入器找不到需要载入的类,那么系统类载入器继续执行载入任务(5)如果系统类载入器找不到需要载入的类,则会抛出异常-java.lang.ClassNotFoundException第4页/共29页第八章 载入器*为什么要做这样一个循环的过程-代理模型的重要用途就是为了解决类载入过程中的安全问题 看个例子:当程序的某个地方调用了自定义的java.lang.O
4、bject类时,系统类载入器会将载入工作 委托给扩展类载入器,继而会被交给引导类载入器。引导类载入器搜索其核心库,找到标准的 java.lang.Object 类,并将之实例化。结果是,自定义的java.lang.Object类并没有被载入。java中类载入机制可以通过继承抽象类java.lang.ClassLoader类编写自己的类载入器。Tomcat使用自定义类载入器原因有三条:为了在载入类中制定某些规则;为了缓存已经载入的类;为了实现类的预载入,方便使用第5页/共29页第八章 载入器 Loader 接口载入web应用程序中需要的servlet类及相关类需要遵循的一些规则:1)应用程序中的
5、servlet只能引用部署在WEB-INF/classes目录及其子目录下的类;2)servlet类不能访问其他路径中的类,即使这些类包含在运行当前的Tomcat的jvm的classpath 环境变量中;3)此外,servlet类只能访问WEB-INF/lib目录下的库,其他目录中的类库不能访问;第6页/共29页第八章 载入器 *Tomcat载入器指的是web应用程序载入器,而不仅仅指类载入器:1)载入器必须实现org.apache.catalina.Loader接口;2)使用自定义类载入器,它是org.apache.catalina.loader.WebappClassLoader类的一个实
6、例;(通过Loader接口的getClassLoader()方法来获取)*Loader接口定义了对仓库的操作:(Tomcat中的仓库就是WEB-INFO/classes目录和 WEB-INF/lib 目录)1)仓库:一个web app的仓库指的是,其WEB-INFO/classes目录和WEB-INF/lib目录,这两个目录作为仓库添加到 载入器中;2)addRepository方法和findRepositories()方法:添加一个新仓库和返回所有仓库集合(数组对象);3)Tomcat的载入器通常会与一个 Context级别的servlet容器相关联;第7页/共29页自动重载:如果Conte
7、xt容器中的一个或多个类被修改了,载入器也可以支持对类的自动重载;1)Loader接口使用modified()方法来支持类的自动重载:如果仓库中的一个或多个类被修改了,那么modified()方法会返回true,才能提供自动重载的支持;2)载入器类本身并不会自动重载:它会调用Context接口(容器)的reload()方法来实现;3)setReloadable()和getReloadable()方法:用来指明是否支持载入器的自动重载;第8页/共29页第八章 载入器4)自动重载的默认情况:默认情况下是禁用了自动重载的功能的,要想启动Context容器的自动重载功能,需要再server.xml文件
8、中添加一个Context元素,如下所示:5)载入器的实现会指明是否要委托给一个父类载入器;(Loader接口中声明了 getDelegate()方法 和 setDelegate()方法)第9页/共29页第八章 载入器6)org.apache.catalina.Loader的声明代码如下:package org.apache.catalina;import java.beans.PropertyChangeListener;public interface Loader public ClassLoader getClassLoader();public Container getContain
9、er();public void setContainer(Container container);public DefaultContext getDefaultContext();public void setDefaultContext(DefaultContext defaultContext);第10页/共29页第八章 载入器 public boolean getDelegate();public void setDelegate(boolean delegate);public String getInfo();public boolean getReloadable();pub
10、lic void setReloadable(boolean reloadable);public void addPropertyChangeListener(PropertyChangeListener listener);public void addRepository(String repository);public String findRepositories();public boolean modified();public void removePropertyChangeListener(PropertyChangeListener listener);第11页/共29
11、页第八章 载入器Catalina提供了org.apache.catalina.loader.WebappLoader 类作为Loader接口的实现:WebappLoader对象中使用 org.apache.catalina.loader.WebappClassLoader 类的实例作为其类载入器,该类继承自 java.NET.URLClassLoader 类;Loader接口及其实现类的UML类图:第12页/共29页第八章 载入器Reloader接口Reloader接口:为了支持类的自动重载功能,类载入器实现需要实现org.apache.catalina.loader.Reloader 接口;
12、最重要的方法:modified方法,其作用是:如果web app中的某个servlet或相关类被修改了,modified方法会返回true第13页/共29页第八章 载入器WebappLoader类(web应用程序载入器,负责载入web应用程序中所使用到的类)如上述的UML类图所示,WebappLoader类实现Runnable接口,它就可以指定一个线程来不断的调用其类载入器的modified()方法,当调用WebappLoader类的start方法时,会完成以下几项重要工作:w1)创建一个类载入器;w2)设置仓库;w3)设置类路径;w4)设置访问权限;w5)启动一个新线程来支持自动重载第14页
13、/共29页第八章 载入器创建类载入器WebappLoader类提供了getLoaderClass()方法 和setLoaderClass()方法来获取或改变其私有变量的loaderClass的值;1)该私有变量保存了一个字符串类型的值,指明了类载入器所要载入的类的名字;2)默认情况下:变量loadClass的值是org.apache.catalina.loader.WebappClassLoader;3)也可以通过继承WebappClassLoader类的方式实现自己的类载入器,然后调用setLoaderClass()方法强制WebappLoader实例使用自定义类载入器。否则的话,在它启动时
14、,WebappLoader类会调用其私有方法createClassLoader()方法来创建 默认的类载入器;第15页/共29页第八章 载入器private WebappClassLoader createClassLoader()throws Exception Class clazz=Class.forName(loaderClass);WebappClassLoader classLoader=null;if(parentClassLoader=null)classLoader=(WebappClassLoader)clazz.newInstance();else Class argTy
15、pes=ClassLoader.class;Object args=parentClassLoader;Constructor constr=clazz.getConstructor(argTypes);classLoader=(WebappClassLoader)constr.newInstance(args);return classLoader;第16页/共29页第八章 载入器设置仓库 WebappLoader类的start()方法会调用setRepositories()方法将仓库添加到其类载入器中。WEB-INF/classes目录被传入到类载入器的addRepository()方法中
16、,而WEB-INF/lib目录被传入类载入器的setJarPath()方法中。设置类路径 在start()方法中调用setClassPath()方法完成。设置访问权限 运行Tomcat时,若使用了安全管理器,则setPermissions()方法会为类载入器设置访问相关的目录权限,若没有使用安全管理器,则此方法什么都不做,只是简单的返回。第17页/共29页第八章 载入器开启新线程执行类的重新载入1)WebappLoader类支持自动重载功能:如果仓库中的类被重新编译了,那么这个类会自动重新载入,无需重启tomcat;2)为了实现这个功能:WebappLoader类使用一个线程周期性地检查每个资
17、源的时间戳。间隔时间由变量 checkInterval 指定,单位为妙。默认case下,checkInterval的值为15,即每隔15秒会检查一次是否有文件需要自动重新载入。getCheckInterval方法和setCheckInterval方法 用于获取和设置间隔时间;3)tomcat4中,WebappLoader类实现 java.lang.Runnable 接口来支持自动重载。第18页/共29页第八章 载入器public void run()if(debug=1)log(“BACKGROUND THREAD Starting”);while(!threadDone)theadSleep
18、();if(!started)break;try if(!classLoader.modified()continue;cat(Exception e)notifyContext();break;if(debug =1)log(“BACKGROUND THREAD Stopping”);第19页/共29页第八章 载入器对以上代码的分析(run方法中while循环会执行以下operations):1)使线程休眠一段时间,时长由变量checkInterval指定,以秒为单位;2)调用WebappLoader 实例的类载入器的modified方法检查已经载入的类是否被修改,若没有类修改,则重新执行循
19、环;3)若某个已经载入的类被修改了,则调用私有方法 notifyContext(),通知与 WebappLoader实例关联的 Context容器重新载入相关类;第20页/共29页第八章 载入器private void notifyContext()WebappContextNotifier notifier=new WebappCotxNotfier();(new Thread(notifier).start();notifyContext()方法不会直接调用Context接口的reload方法,它会实例化一个内部类WebappContextNotifier,将其传入一个新建的线程对象中,并
20、调用线程的start()方法,此时会执行WebappContextNotifier 实例的run()方法,run()方法会调用Context接口的reload()方法。class WebappContextNotifier implements Runnablepublic void run()(Context)container).reload();第21页/共29页第八章 载入器WebappClassLoader类web 应用程序中负责载入类的类载入器是:org.apache.catalina.loader.Webapp ClassLoader类的实例;此类继承自.URLClassLoad
21、er类。优化:缓存已经加载的类;缓存加载失败的类的名字,下次 再加载的时候,直接抛出NotFound异常 安全性:不允许载入指定的某些类,名字储存在变量triggers 中,某些特殊的包及其子包下的类也不允许载入,也不将载入类的任务委托给系统类载入器去执行。第22页/共29页第八章 载入器类缓存1)java.lang.ClassLoader类会维护一个Vector对象,保存已经载入的类,防止这些类在不使用时当做垃圾而回收;2)资源:每个由 WebappClassLoader 载入的类(无论是在WEB-INF/classes 目录下还是从某个JAR 文件内作为类文件部署),都视为资源;资源是 o
22、rg.apache.catalina.loader.ResourceEntry 类的实例。3)所有已经缓存的类会存储在resourceEntries的HashMap类型的变量中,其key值就是载入资源的名称,载入失败的类的名称会存储到另一个名为notFoundResource的HashMap类型的变量中。第23页/共29页第八章 载入器public class ResourceEntry public long lastModified=-1;public byte binaryContent=null;public Class loadedClass=null;public URL sour
23、ce=null;public URL codeBase=null;public Manifest manifest=null;public Certificate certificates=null;第24页/共29页第八章 载入器载入类(WebappClassLoader需要遵守的规则)1)因为所有已经载入的类都会缓存起来,所以载入类时要先检查本地缓存;2)若本地缓存中没有,则检查上一层缓存,即调用 java.lang.ClassLoader 类的findLoadedClass()方法;3)若两个缓存中都没有,则使用系统的类载入器进行加载,防止 web 应用程序中的类覆盖J2EE 的类;4)
24、若启用了 SecurityManager,则检查是否允许载入该类。若该类是禁止载入的类,抛出 ClassNotFoundException异常;5)若打开标志位 delegate,或者待载入的类是属于包触发器中的包名,则调用父载入器来载入相关类。如果父载入器是null,则使用系统的类载入器;6)从当前仓库中载入相关的类;7)若当前仓库中没有需要的类,且标志位delegate关闭,则使用父类载入器。若父类载入器为 null,则使用系统的类载入器进行加载;8)若仍未找到需要的类,则抛出 ClassNotFoundException 异常。第25页/共29页第八章 载入器应用程序1)应用程序目的是为
25、了说明:如何使用与某个Context容器相关联的WebappLoader实例;(2)而Context接口的标准实现:org.apache.catalina.core.StandardContext;3)我们需要知道的是:监听器和可以触发事件。如StandardContext类是如何与监听它触发的事件(如START_EVENT and STOP_EVENT)的监听器协同工作的;4)监听器必须实现接口:org.apache.catalina.lifecycle.LifecycleListener接口;而监听器的一个实例是 SimpleContextConfig类第26页/共29页第八章 载入器总结1)web 应用程序中的载入器,或一个简单的载入器,都是 Catalina中最重要的组件;2)载入器负责载入应用程序所需要的类,因此会使用一个内部类载入器:这个内部类载入器是一个自定义类,tomcat使用这个自定义的类载入器对 web应用程序上下文中要载入的类进行一些约束;3)此外,自定义类载入器可以支持对载入类的缓存和对一个或多个被修改的类的自动重载;第27页/共29页 thanks!第28页/共29页感谢您的观看!第29页/共29页
限制150内