Tomcat架构解析之类加载器

一、前言

    主要介绍Tomcat的类加载机制,包括Tomcat的类加载器层级设计以及Web应用的类加载过程。类加载是一切Java应用运行的基础,了解一款应用的类加载机制会便于我们掌握他的运行边界,也有助于其运行异常的快速定位。

二、J2SE类加载器

    JVM迷人提供了3个类加载器,他们以一种父子树的方式创建,同时使用委派模式确保应用程序可以通过自身的类加载器(System)加载所有可见的Java类。

结构图如下所示:
在这里插入图片描述

  • Bootstrap:用于加载JVM提供的基础运行类,即位于%JAVA_HOME%hre/lib目录下的核心类库。
  • Extension:Java提供的一个标准的扩展机制用于加载除核心类库的jar包,即只要复制到指定的扩展目录(可以多个)下的jar,JVM会自动加载默认扩展目录是%JAVA_HOME%jre/libext。典型的应用场景就是,Java使用该类加载器加载JVM默认提供的但是不属于核心类库的Jar,如JCE等。不推荐将应用程序依赖的库类放置到扩展目录下,以为该目录下的类库对所有基于该JVM运行的应用程序可见。
  • System:用于加载环境变量CLASSPATH(不推荐使用)指定目录下的或者-classpath运行参数指定的jar包。System类加载器通常用于加载应用程序jar包以及其启动入口类(Tomcat的Bootstrap类即由System类加载器加载)。

    应用程序在不是自己构造类加载器的情况下,使用System作为默认的类加载器。如果应用程序自己构造类加载器,基本也以System作为父类加载器。

    除了支持类加载器按照层级创建外,JVM还提供了一套称作Endorsed Standards Override Mechanism的机制用于允许替换JCP之外生成的API。通过这个机制,应用程序可以提供新版本的API来覆盖JVM的默认实现。

    之所以存在这套机制是以为随着版本的不断更新,J2SE包含越来越多的扩展,这些扩展由JVM加载所有应用程序使用(如JAXP),甚至作为核心类库(位于rt.jar)由于Bootstrap类加载器加载,因此,即便应用程序提供了新版本的JAXP包,新版本也不会被使用。此时,我们可以通过Endorsed Standands机制来解决该问题。

    JVM默认的Endorsed目录为%JAVA_HOME%/lib/endorsed,当然,我们可以通过指定启动参数java.endorsed.dir来修改。只要是复制到该目录下的Jar包,将优先于JVM中的类加载。

    之所以在此处提到Endorsed Standands机制,是因为很多应用服务器都使用了该机制来提供新版本的Jar包,比如JBoss。虽然Tomcat没有相关的目录,但是在启动参数中是包含相关配置的,默认为$CATALINA_HOME/endorsed。

三、Tomcat加载器

应用服务器通常会自行创建类加载器以实现更加灵活的控制,这一方面是对规范的实现(Servlet规范要求每个Web应用都有一个独立的类加载器实例),另外一方面也有架构层面的考虑。

  • 隔离性:Web应用类库相互隔离,避免依赖库或者应用包互相影响。
  • 灵活性:既然Web应用之间的类加载器将会重新创建,而且不会影响其他Web应用。如果采用一个类加载器,显然无法实现,因为只有一个类加载器的时候,类之间的依赖是杂乱无章的,无法完整的已出某个Web应用的类。
  • 性能:由于每个Web应用都有一个类加载器,因此Web应用在加载类时候,不会搜索其他Web应用包含的Jar包,性能自然高于应用服务器只有一个类加载器的情况。

    当然,Tomcat的类加载器设计也体现了机电架构要素,Tomcat的类加载方案如下所示:
在这里插入图片描述
    可以看到,除了每个Web应用的类加载器外,Tomcat也提供了3个基础的类加载器和Web应用类加载器,而且这3个类加载器指向的路径和包列表均可以由catalina.properyies配置。

  • Common:以System为父加载器,是位于Tomcat应用服务器顶层的公用类加载器。其路径为common.loader,默认指向$SCATALINA_HOME/lib下的包。
  • Catalina:以Common为父加载器,是用于加载Tomcat应用服务器的类加载器,其路径为server.loader,默认为空。此时Tomcat使用Common类加载器加载应用服务器。
  • Shared:以Common为父加载器,是所有Web应用的父加载器,其路径为shared.loader,默认为空。此时Tomcat使用CommonCommon类加载器作为Web应用父加载器。
  • Web应用:以Shared为父加载器,加载/WEB-INF/classes目录下的未压缩的Class和资源文件以及/WEB-INF/lib目录下的jar包。如前所述,该类加载器只对当前Web应用可见,对其他Web应用均不可见。

    尽管默认情况下,这3个基础类加载器是同一个,但是我们可以通过配置创建3个不同的类加载器,使他们各司其职。

    首先,Common类加载器负责加载Tomcat应用服务器内部和Web应用均可见的类,例如Servlet规范相关包和一些通用的工具包。

    其次,CatAlina类加载器负责加载只有Tomcat应用服务器内部可见的类,这些类对Web应用不可见。如Tomcat的具体实现类,因为我们的Web应用最好与服务器送耦合,故不应该依赖应用服务器的内部类。

    再次,Shared类加载器负责加载Web应用共享的类,这些类Tomcat服务器不会依赖。

    最后,Tomcat服务器$CATALINA_HOME/bin目录下的包作为启动入口由System类加载器加载。通过将这几个启动包剥离,Tomcat简化了应用服务器的启动,同时增加了灵活性。

下面几点是对上述架构分析的补充:

  • 共享:Tomcat通过Common类加载器实现了Jar包在应用服务器以及Web应用之间共享,通过Shared类加载器实现了Jar包在Web应用之间的共享,而且又确保了不会引入过多的无用的包。
  • 隔离性:这里的隔离性不同于上面的,这里的是指服务器与Web应用的隔离。理论上,出去Servlet规范定义的接口外,我们的Web应用不应该依赖服务器的任何实现类,这样才有助于Web应用的可移植性。正因为如此,Tomcat支持通过Catalina类加载器加载服务器依赖的包(尽管Tomcat默认并没有这么做),以便于应用服务器与Web应用更好的隔离。

四、Web应用类加载器

Java默认的类加载机制是委派模式,委派过程如下:

  1. 从缓存中加载。
  2. 若缓存中没有,则从父类加载器中加载。
  3. 如果父类加载器没有,则从当前类加载器加载。
  4. 如果没有,则抛出异常。

    Tomcat提供的Web应用类加载器与默认的委派模式稍有不同。当进行类加载时,除了JVM基础类库外,他会首先尝试通过当前类加载器加载,然后才进行委派。Servlet规范相关API禁止通过Web应用类加载器加载,因此,不要在Wen应用中包含这些包。

    因此,Web应用类加载器默认加载顺序如下:

  • 从缓存中加载。
  • 若缓存中没有,则从JVM的Bootstrap类加载器加载。
  • 如果没有,则从当前类加载器加载(安装WEB-INF/class、WEB-INF/lib的顺序)。
  • 如果没有,则从父类加载器加载,由于父类加载器采用默认的委派模式,所以加载顺序为System、Common、Shared。

    Tomcat提供了delegate属性用于控制是否启动Java委派模式,默认为false,当配置为true时,Tomcat将使用Java默认的委派模式,即按如下顺序加载:

  • 从缓存中加载。
  • 若缓存中没有,则从JVM的Bootstrap类加载器加载。
  • 若没有,则从弗雷加载器加载(System、Common、Shared)。
  • 若没有,则从当前类加载器加载。

    除了可以通过delegate属性控制是否启用Java的委派模式之外,Tomcat还可以通过packageTriggersDeny属性只让某些包路径采用Java的委派模式,Web应用类加载器对于符合packageTriggersDeny指定包路径的类强制采用Java的委派模式。

五、总结

    Tomcat通过该机制实现为Web应用中的Jar包覆盖服务器包的目的。如上所述,Java核心类库、Servlet规范相关类库是无法覆盖的,此外Java默认提供的例如XML工具包,由于位于JVM的Bootstrap类加载器也无法覆盖,只能通过endorsed的方式实现。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值