tomcat的类加载器

一.Jvm的类加载器

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

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

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

二.Tomcat的类加载器

官方文档

  1. Common:以System为父类加载器,是位于Tomcat应用服务器顶层的公用类加载器。其路径为common.loader,默认指向$CATALINA_HOME/lib下的包。

  2. Catalina: 以Common为父加载器,是用于加载Tomcat应用服务器的类加载器,其路径为server.loader,默认为空。此时Tomcat使用Common类加载器加载应用服务器。

  3. Shared:以Common为父加载器,是所有Web应用的父加载器其路径为shared.loader ,默认为空。此时Tomcat使用Common类加载器作为Web应用的父加载器。

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

从Web应用程序的角度来看,类或资源的加载按以下顺序查找以下存储库

  • Bootstrap classes of your JVM

  • /WEB-INF/classes of your web application

  • /WEB-INF/lib/*.jar of your web application

  • System class loader classes (described above)

  • Common class loader classes (described above)

三.Tomcat类加载器这样设计的优点

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

  1. 隔离性: Web应用类库相互隔离,避免依赖库或者应用包相互影响。设想一下,如果我们有两个Web应用,一个采用了Spring2.5,一个采用了Spring 4.0,而应用服务器使用一个类加载器加载,那么Web应用将会由于Jar包覆盖而导致无法启动成功。

  2. 灵活性:既然Web应用之间的类加载器相互独立,那么我们就能只针对一个Web应用进行重新部署,此时该Web应用的类加载器将会重新创建,而且不会影响其他Web应用。如果采用一个类加载器,显然无法实现,因为只有一个类加载器的时候,类之间的依赖是杂乱无章的,无法完整地移除某个Web应用的类。

  3. 性能:由于每个Web应用都有一个类加载器,因此Web应用在加载类时,不会搜索其他 Web应用包含的Jar包,性能自然高于应用服务器只有一个类加载器的情况。

四.Tomcat类加载器的实现

Bootstrap:initClassLoaders();

  1. commonLoader = createClassLoader("common", null);

  2. catalinaLoader = createClassLoader("server", commonLoader);

  3. sharedLoader = createClassLoader("shared", commonLoader);

digester的创建:

  1. Catalina:createStartDigester();

  2. Digester digester = new Digester();

创建类的过程:

  1. ObjectCreateRule:begin();

    1. Class<?> clazz = digester.getClassLoader().loadClass(realClassName);

  2. SetNextRule:end();

    1. IntrospectionUtils.callMethod1(parent, methodName,child, paramType, digester.getClassLoader());

    2. digester.getClassLoader();

    3. Thread.currentThread().getContextClassLoader();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值