Tomcat内核之类加载器工厂

Java虚拟机利用类加载器将类载入内存,以供使用。在此过程中类加载器要做很多的事情,例如读取字节数组、验证、解析、初始化等。而Java提供的URLClassLoader类能方便地将jar、class或网络资源加载到内存。Tomcat中则用一个工厂类ClassLoaderFactory把创建类加载器的细节进行封装,通过它可以很方便地创建自定义的类加载器。
 
如上图,利用createClassLoader方法并传入资源路径跟父类加载器即可创建一个自定义类加载器,此类加载器负责加载传入的所有资源。
ClassLoaderFactory有个内部类Repository,它就是表示资源的类,资源的类型用一个RepositoryType枚举表示,即public static enum RepositoryType {DIR,GLOB,JAR,URL}。每个类型代表的意思如下:
DIR:表示整个目录下的资源,包括所有clsss、jar包及其它类型资源。
GLOB:表示整个目录下所有jar包资源,仅仅是.jar后缀的资源。
JAR:表示单个jar包资源。
URL:表示网络上得某个jar包资源。
通过以上介绍已经对ClassLoaderFactory类有所了解,下面用一个简单的例子展示tomcat中的CommonLoader是如何利用ClassLoaderFactory工厂类来创建的,如下:
List<Repository> repositories = new ArrayList<Repository>();
Repositories.add(new Repository(“${catalina.home}/lib”,RepositoryType.DIR));
Repositories.add(new Repository(“${catalina.home}/lib”,RepositoryType.GLOB));
Repositories.add(new Repository(“${catalina.base}/lib”,RepositoryType.DIR));
Repositories.add(new Repository(“${catalina.base}/lib”,RepositoryType.GLOB));
ClassLoader parent = null;
ClassLoader commonLoader = ClassLoaderFactory.createClassLoader(repositories, parent);
OK,至此CommonLoader创建完毕。其中${catalina.home}跟${catalina.base}表示变量,它的值分别为tomcat安装目录与tomcat的工作目录,您只需要替换成实际路径即可。Parent为父类加载器,如果设置为null,ClassLoaderFactory创建时会使用默认的父类加载器,即系统类加载器systemClassLassLoader。实际上,您只需以下几步就能完成一个类加载器的创建,首先,把要加载的资源都添加到一个List中;其次,确定父类加载器,默认的话就设置为null;最后,把这些作为参数传入ClassLoaderFactory工厂类。
假如我们不确定要加载的资源是在网络上的还是本地的,那么可以用以下方式进行处理:
try {
     URL url = new URL(“路径”);
     repositories.add(new Repository(“路径”, RepositoryType.URL));
     } catch (MalformedURLException e) {
 }
这种方式处理得比较巧妙,URL在实例化时就可以检查这个路径的有效性,假如为本地资源或者网络上不存在此路径的资源,那么将抛出异常,不会把此路径添加到资源列表。
在此有必要对ClassLoaderFactory工厂类的createClassLoader进行简单说明,它是一个重载方法,参数列表不同,但是不管怎样,最终都要转成URL[]数组,因为ClassLoaderFactory生产的类加载器是继承于URLClassLoader,而URLClassLoader的构造函数只支持URL[]数组。从Repository类转成URL[]数组可分为以下情况:
① 若为RepositoryType.URL类型的资源,则直接new一个URL实例添加到URL[]数组即可。
② 若为RepositoryType.DIR类型的资源,则要把File类型转化为URL类型,由于URL类用于网络,带有明显的协议,于是把本地文件的协议定为file,即处理为new URL(“file:/D:/test/”),最后的”/”切记要加上,它表示D盘test整个目录下的所有资源,最后把这个URL实例添加到URL[]数组中。
③ 若为RepositoryType.JAR类型的资源,则跟②中类似,本地文件协议为file,处理为new URL(“file:/D:/test/test.jar”),然后把这个URL实例添加到URL[]数组中。
④ 若为RepositoryType.GLOB类型的资源,则找到某个目录下的所有文件,然后依个判断是不是以.jar后缀结尾,如果是,则跟③一样转化,再将URL实例添加到URL[]数组中。如果不是以.jar结尾,则直接忽略。

现在对类加载器工厂ClassLoaderFactory有了更深的了解,知道了怎样轻松建立一个类加载器实例,并且了解了其中的细节实现。

点击订购作者《Tomcat内核设计剖析》

时间: 2024-09-15 22:13:25

Tomcat内核之类加载器工厂的相关文章

Tomcat内核之Tomcat的类加载器

跟其他主流的Java Web服务器一样,Tomcat也拥有不同的自定义类加载器,达到对各种资源库的控制.一般来说,Java Web服务器需要解决以下四个问题: ①   同一个Web服务器里,各个Web项目之间各自使用的Java类库要互相隔离. ②   同一个Web服务器里,各个Web项目之间可以提供共享的Java类库. ③   服务器为了不受Web项目的影响,应该使服务器的类库与应用程序的类库互相独立. ④   对于支持JSP的Web服务器,应该支持热插拔(hotswap)功能. 对于以上几个问

黑马程序员 十六、 类加载器、代理

Java帮帮-IT资源分享网 1.类加载器 一.概述: 1.定义:简单说,类加载器就是加载类的工具. 当出现一个类,用到此类的时候,Java 虚拟机首先将类字节码加载进内存,通常字节码的原 始信息放在硬盘上的 classpath 指定的目录下. 2.类加载器作用:将.class 文件中的内容加载进内存进行处理,处理完后的结果就是字节码. 3.默认类加载器: 1)Java 虚拟机中可安装多个类加载器,系统默认的有三个主要的,每个类负责加载特定位 置的类:BootStrap.ExtClassLoad

类加载器的双亲委派及打破双亲委派

一般的场景中使用Java默认的类加载器即可,但有时为了达到某种目的又不得不实现自己的类加载器,例如为了达到类库的互相隔离,例如为了达到热部署重加载功能.这时就需要自己定义类加载器,每个类加载器加载各自的类库资源,以此达到资源隔离效果.在对资源的加载上可以沿用双亲委派机制,也可以打破双亲委派机制. 一.沿用双亲委派机制自定义类加载器很简单,只需继承ClassLoader类并重写findClass方法即可.如下例子: ①先定义一个待加载的类Test,它很简单,只是在构建函数中输出由哪个类加载器加载.

Java 类加载器(转)

 java虚拟机中可以安装多个类加载,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap(内嵌在java虚拟机中由C++编写),ExtClassLoader,AppClassLoad    类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap.    java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象    或

java自定义类加载器

v前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是eclipse项目中的bin目录里),然后通过java反射机制,获取main方法并执行..class文件名称固定.当 A.class文件更新的时候,问题出现了,main方法的执行结果总和第一次的执行结果相同. v程序流程 代码提交->接收代码->编译成A.class文件->java反射->

java虚拟机如何查找已加载的类?java虚拟机在代码中为指定类加载器时如何选择类加载器?

问题描述 java虚拟机如何查找已加载的类?java虚拟机在代码中为指定类加载器时如何选择类加载器? tomcat不同webapp相互隔离是怎么做到的? 通过不同webapp使用不同的类加载器加载做到的? 怎么指定某个webapp使用哪个类加载器?不是每个类都用classLoader.loadClass()吧.

Java类加载器(一)——类加载器层次与模型

类加载器   虚拟机设计团队把类加载阶段中的"通过一个类的全限定名来获取描述此类的二进制字节流"这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为"类加载器". 类加载器层次(等级)   从JVM的角度来讲,只存在两种不同的类加载器.   第一类是启动类加载器(Bootstrap ClassLoader):这个类加载器主要加载JVM自身工作需要的类.这个类加载器由C++语言实现(特指HotSpot),是虚拟机

创建一个简单的web服务器(二):使用自定义的类加载器来替换URLClassLoader

在上一章中我们加载Servlet用的是URLClassLoader,在这一章中我们使用自定义的类加载器来替换URLClassLoader.关于类加载器的文章请参考这里:深入探讨 Java 类加载器.这篇文章写得很棒. 具体的代码如下: package com.zkn.imitate.tomcat.secondchapter.first; import com.zkn.imitate.tomcat.secondchapter.Request; import com.zkn.imitate.tomc

java动态代理类加载器 作用 限制 要求

问题描述 方法Proxy.newProxyInstance(ClassLoaderloader,Class<?>[]interfaces,InvocationHandlerh)中的类加载器(loader)的指定到底有什么限制,是不是随便给一个类加载器就可以了阿,其作用是什么? 解决方案 解决方案二:我的理解:加载器应该就是虚拟机的一部分.java编程思想里是这样说的:你通常可以从已经被加载的对象中获得其类加载器.一般使用当前类的加载器就行了,xxx.class.getClassLoader()