在Java语言中,类型的加载和连接过程都是在程序运行期间完成的,尽管这样会带来一定的开销,但是却能为Java应用程序提供高度的灵活性,Java的动态扩展属性正是依赖运行期动态加载和动态连接这个特点实现的。
![](https://img-my.csdn.net/uploads/201212/17/1355751633_1294.JPG)
![](https://img-my.csdn.net/uploads/201212/17/1355751674_8904.JPG)
server.loader与shared.loader这两项的配置都是空的。在新的类加载层次结构中只剩下StandardClassLoader与WebAppClassLoader, StandardClassLoader扮演着加载系统类库的作用,是WebAppClassLoader父类加载器。每个Web应用类加载器(WebAppClassLoader)对应一个Web应用,它负载加载/WEB-INF/classes与/lib中的类。
Java中类的整个生命周期为:加载->验证->准备->解析->初始化->使用->卸载。类加载器便是作用于"加载"阶段,它完成的功能为:通过一个类的全限定名来获取描述此类的二进制字节流“,Java将这个动作放到Java虚拟机外部去实现,允许应用程序自己决定如何去获取所需要的类,也因此,我们可以自定义自己的类加载器。类加载器可是说是在各种各样的框架(spring,OSGI),服务器(tomcat)中大放异彩。
Java中的类加载器大致可以分为几类,一类是系统提供的,另外一类则是Java应用开发人员编写的。系统提供的类加载器主要有下面三个:
(1)引导类加载器(Bootstrap ClassLoader),这个类加载器负责将存放在<JAVA_HOME>\lib目录中的类库加载到虚拟机内存中。它采用原生代码来实现,并不继承自java.lang.ClassLoader。
(2)扩展类加载器(Extension ClassLoader):这个加载器由sun.misc.Launcher$ExtClassLoader实现,负责加载Java的扩展库,也即<JAVA_HOME>\jre\lib\ext目录中的类库,或者java.ext.dirs系统变量所指定的路径中所有的类库。
(3)应用程序类加载库(Application ClassLoader),也称系统类加载器,它可以通过getSystemClassLoader()方法获得。它根据Java应用的类路径来加载Java类。一般来说,Java应用的类都是由它来完成加载的。
除了引导类加载之外,所有的类加载器都有一个父类加载器。对应系统类加载器来说,扩展类加载器的父类为引导类加载器,应用程库类加载器的父类则为扩展类加载器,而开发人员开发的自定义类加载器的父类则为加载此类的类加载器。我们将这样的层次关系称为双亲委派模型。双亲委派模型要求除了顶层的引导类加载器外,其余的类加载器都应有自己的父类加载器。其模型图如下所示:
双亲委派模型的工作过程是:如果一个类加载收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的引导类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。想对此有更深入的理解的亲可以自己写个类,在此类中通过this.getClass().getClassLoader()打印类加载器,打包成jar后,放到jre\lib\ext之类的地方,以此来检验双亲委派模型如何作用。
继续看看tomcat的类加载器层次结构:
首先进行责任声明:”此图来自网上,并非本人所画,因为实在是懒“,这个图是tomcat5.5(印象中是)前的类加载层次,6.0开始CatalinaLoader和ShareLoader这两个类加载器默认是不启用的,除非你自己去配置,这一点可以从配置文件catalina.properities中看出:
# "foo/bar.jar": Add bar.jar as a class repository
common.loader=${catalina.home}/lib,${catalina.home}/lib/*.jar
#
# List of comma-separated paths defining the contents of the "server"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
# If left as blank, the "common" loader will be used as Catalina's "server"
# loader.
# Examples:
# "foo": Add this folder as a class repository
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
server.loader=
#
# List of comma-separated paths defining the contents of the "shared"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_BASE path or absolute. If left as blank,
# the "common" loader will be used as Catalina's "shared" loader.
# Examples:
# "foo": Add this folder as a class repository
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
# Please note that for single jars, e.g. bar.jar, you need the URL form
# starting with file:.
shared.loader=
server.loader与shared.loader这两项的配置都是空的。在新的类加载层次结构中只剩下StandardClassLoader与WebAppClassLoader, StandardClassLoader扮演着加载系统类库的作用,是WebAppClassLoader父类加载器。每个Web应用类加载器(WebAppClassLoader)对应一个Web应用,它负载加载/WEB-INF/classes与/lib中的类。