J2SE与Tomcat的类加载器

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

    委派模式过程如下

    1、从缓存中加载

    2、如果缓存中没有,则从父类加载器中加载

    3、如果父类加载没有,则从当前类加载器加载

    4、如果没有,则抛异常

    我们先看看J2SE提供的三个类加载,具体结构图在最下方:

    J2SE标准类加载

    1、Bootstrap:用于加载JVM提供的基础运行类,即位于jre/lib目录下的核心类库。

    2、Extension:Java提供的一个标准的可扩展机制用于加载除核心类库外的Jar包,即只要复制到指定的扩展目录(可以多个)下的Jar,JVM会自动加载(不需要通过 -classpath指定)。默认的扩展目录是jre/lib/ext。典型的应用场景就是,Java使用该类加载器加载Jvm默认提供的但是不属于核心类库的jar,如JCE等。不推荐将应用程序依赖的类库放置到扩展目录下,因为该目录下的类库对所有基于该JVM运行的应用程序可见。

    3、System:用于加载环境变量CLASSPATH(不推荐使用)指定目录下的或者-Classpath运行参数指定的Jar包,System类加载器通常用于加载应用程序Jar包及其启动入口类(Tomcat的Bootstrap类即由System类加载器加载)

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

    我们看完了J2Se提供的类加载器,下面看看Tomcat中扩展的类加载器,Tomcat扩展的类加载器结构图也在最下面的图中。从图中我们可以看到,除了每个web应用的类加载器除外,Tomcat也提供了3个基础的类加载器和web应用加载器,而且这3个类加载器指向的路径和包列表均可以由catalina.properties配置。

    Tomcat类加载器

    1、Common:以System为父类加载器,是位于Tomcat应用服务器顶层的公用类加载器。负责加载Tomcat应用服务器内部和web应用均可见的类,例如Servlet规范相关包和一些通用的工具包。其路径为common.loader,默认指向$CATALINA_HOME/lib下的包。

    2、Catalina:以Common为父加载器,是用于加载Tomcat应用服务器的类加载器,负责加载只有Tomcat应用服务器内部可见的类,这些类对web应用不可见,如Tomcat的具体实现类,因为我们的web应用最好和服务器解耦,所以不应该依赖应用服务器的内部类。其路径为server.loader,默认为空,此时Tomcat使用Common类加载器加载应用程序。

    3、shared:以Common为父加载器,是所有web应用的类加载器,负责加载web应用共享的类,这些类Tomcat服务器不会依赖。其路径为shared.loader,默认为空,此时Tomcat使用Common类加载器加载应用程序。

    4、Web应用:以Shared为父类加载器,加载/WEB-INF/classes目录下的未压缩的Class和资源文件以及/WEB-INF/lib目录下的jar包,该类加载器只对当前Web应用可见,对其他Web应用均不可见。

    在tomcat默认情况下,这3个基础类加载器是同一个,但是我们可以通过配置创建3个不同的类加载器,是他们各司其职。举个例子:如果我们想实现自己的会话存储方案,而且该方案依赖了一些第三方包,我们不希望这些包对web应用可见,此时我们可以配置server.loader,创建独立的Catalina类加载器。

    接下来,我们从架构层面讨论一下Tomcat的类加载器方案:

    1、共享:Tomcat通过Common类加载器实现了jar包在应用服务器以及web应用之间共享,通过shared类加载器实现了jar包在web应用之间的共享,通过Catalina类加载器,加载服务器依赖的类,这样最大程度上实现了jar包的共享,而且又确保了不会引入过多无用的包。

    2、隔离性:这里的隔离性区别与前者,指服务器与web应用隔离,理论上,除去Servlet规范定义的接口外,我们的web应用不应依赖服务器的任何实现类,这样才有助于web应用的可移植性



 

猜你喜欢

转载自hejiawangjava.iteye.com/blog/2394754
今日推荐