类的双亲委派机制

启动类加载器Bootstrap ClassLoader -> lib
扩展类加载器Extension ClassLoader -> ext
应用程序类加载器 Application ClassLoader

  • 防止重复加载

    原因

    无法实现隔离性

    如果使用默认的类加载器机制,那么是无法加载两个相同类库的不同版本,默认类加载器是不管你是什么版本的,只在乎你的全限类名,并且只有一份。一个web容器可能要部署两个或者多个应用程序,可能会依赖同一个第三方类库的不同版本,因为要保证每一个应用程序的类库都是独立的、相互隔离的。部署在同一个web容器中的相同类库的相同版本可以共享,否则,会有重复的类库被加载进JVM,web容器也有自己的类库,不能和应用程序的类库混淆,需要相互隔离。

    无法实现热替换

    jsp文件其实也是class文件,如果修改了,但是类名还是一样,类加载器会直接取方法区中已经存在的,修改后的jsp是不会重新加载的。
    打破双亲委派机制OSGI 是基于Java语言的动态模板化规范,类加载器之间是网状结构,更加灵活,也更加复杂。

    tomcat的自定义类加载器

    CommonClassLoader

    最基本的类加载器,加载路径中的class可以被tomcat和各个webapp访问

    CatalinaClassLoader

    tomcat私有类加载器,webapp不能访问其加载路径下的class, 对webapp不可见

    ShareClassLoader

    各个webapp共享的类加载器,对tomcat不可见

    WebappClassLoader

    webapp私有的类加载器,只对当前webapp可见。

每一个web应用程序对应一个webappClassLoader, 每一个jsp文件对应一个JspClassLoader, 所以这两个类加载器有多个实例

工作原理

  • CommonClassLoader能加载的类都可以被Catalina ClassLoader和SharedClassLoader使用,从而实现了公共类库的公用。
  • CatalinaClassLoader和SharedClassLoader自己能加载的类则与对方互相隔离
  • WebappClassloader可以使用SharedClassLoader加载到的类,但各个webappClassLoader实例相互隔离,多个webappClassLoader是同级关系
  • JasperClassLoader的加载范围仅仅是这个JSP文件编译出来的一个.Class文件,它出现的目的就是为了被废弃;当web容器检测到JSP文件被修改时,会替换成目前的JasperLoader的实例,并通过再建立一个新的JSP类加载器来实现JSP文件的HotSwap功能