Tomcat之类加载器
分析Tomcat是避不开tomcat的类加载机制
类加载器
Java中的类遵循按需加载。
类加载器:就是用于加载 Java 类到 Java 虚拟机中,它负责读取 Java 字节码,并转换成 java.lang.Class 类的一个实例,使字节码.class 文件得以运行。
类加载器在实际使用中可以使 Java 类动态地加载到 JVM 中并运行,即是可在程序运行时再加载类,提供了灵活的动态加载方式。
1、启动类加载器(Bootstrap ClassLoader):负责加载 <JAVA_HOME>/jre/lib 目录下 JVM 指定的类库。其实它属于 JVM 整体的一部分,JVM 一启动就将这些指定的类加载到内存中。无法被 Java 程序直接使用。
2、扩展类加载器(Extension ClassLoader):加载的对象为 Java 的扩展库,即加载 <JAVA_HOME>/jre/lib/ext 目录下面的类。如果调用扩展类加载器的 getParent()方法获取父加载器会得到 null。但是,它的父类加载器是启动类加载器。
3、应用程序类加载器(Application ClassLoader):也叫系统类加载器(System ClassLoader),它负责加载用户类路径(CLASSPATH)指定的类库,如果程序没有自己定义类加载器,就默认使用应用程序类加载器。它也由启动类加载器加载,但它的父加载类被设置成了扩展类加载器。如果要使用这个加载器,可通过 ClassLoader.getSystemClassLoader()获取
双亲委派
image.png如果是java.lang.System类,则会在4加载。如果是自定义的com.xx.Order类,则会在6加载
双亲委派模型会在类加载器加载类时首先委托给父类加载器加载,除非父类加载器不能加载才自己加载。
安全性
通过这个机制保证了安全性。设想如果应用程序类加载器想要加载一个有破坏性的 java.lang.System 类,双亲委派模型会一层层向上委派,最终委派给启动类加载器,而启动类加载器检查到缓存中已经有了这个类,并不会再加载这个有破坏性的 System 类。
全盘负责机制
类加载器拥有全盘负责机制,当一个类加载器加载一个类时,这个类所依赖的、引用的其他所有类都由这个类加载器加载,除非在程序中显式地指定由另外一个类加载器加载。
隔离机制
在 Java 中,我们用完全匹配类名来标识一个类,即用包名和类名。而在 JVM 中,一个类由完全匹配类名和一个类加载器的实例 ID 作为唯一标识。也就是说,同一个虚拟机可以有两个包名、类名都相同的类,只要它们由两个不同的类加载器加载。当我们在 Java 中说两个类是否相等时,必须在针对同一个类加载器加载的前提下才有意义,否则,就算是同样的字节码,由不同的类加载器加载,这两个类也不是相等的。这种特征为我们提供了隔离机制,在 Tomcat 中它是十分有用的
Tomcat中的类加载器
image.pngTomcat 拥有不同的自定义类加载器,以实现对各种资源库的控制。
一般来说,Tomcat主要用类加载器解决以下问题:
1、同一个Tomcat中(在同一个JVM),各个Web应用之间各自使用的Java类库要互相隔离。
2、同一个Tomcat中,各个Web应用之间可以提供共享的Java类库。
3、为了使Tomcat不受Web应用的影响,应该使服务器的类库与应用程序的类库互相独立。
4、Tomcat支持热部署
通过创建新的Web应用类加载器达到热部署,在把war包放入到webapps目录便可自定解压部署,就是热部署
CommonClassLoader
Common 类加载器,负责加载$CATALINA_ BASE/lib、$CATALINA_HOME/lib 两个目录下所有的.class 文件与.jar 文件,它的父类加载器是应用程序类加载器
WebAppClassLoader
Web应用类加载器 ,每个类加载器负责加载一个Web 程序。 加载当前web应用的WEB-INF/lib下的jar文件中和WEB-INF/classes下的文件。
它的父类加载器是Common类加载器。由于每 Web应用都有自己的WebApp类加载器,这样应用程序之间便互相隔离。
tomcat怎么违背了双亲委派模型:
为了实现隔离型,每个web应用应当使用自己的web应用类加载器加载,并没有交给父类加载器加载。
总结:
这里只是纯理论,主要包括JVM的各种类加载器(包括自定义类加载器)及其加载路径
tomcat的各种自定义类加载器及其打破双亲委派的原因