tomcat java.ext.dirs_tomcat classloader 加载class顺序

今天下午被同事问到如果我有两个不同版本的class分别放在两个module里如何处理(我们项目里的module是分布在不同的war包里的)

然后引出下面的问题

1. 完全相同(同包同名)的class如何加载

2. 完全相同的class如果在不同war包里如何加载

印象中应该是不同war包各自加载自己的, 猜测是因为会启动各自的application级别classloader, 稍微调查之后发现自己原来的认识不够深入

参考 http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html

我们知道jvm加载class默认是采用 父类委托 模型, 这个模型在之前的文章中我提到过

参考 http://lizhe.name.csdn.net/node/91

java默认提供3种classloader

1. Bootstrp loader

加载%JAVA_HOME%/jre/lib,-Xbootclasspath参数指定的路径以及%JAVA_HOME%/jre/classes中的类

2. ExtClassLoader

加载%JAVA_HOME%/jre/lib/ext,此路径下的所有classes目录以及java.ext.dirs系统变量指定的路径中类库

3. AppClassLoader

加载classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器

getSystemClassLoader 返回的就是这个加载器

当一个classloader需要去加载类com.test.A时, 它首先会在自己的加载缓存中查找这个类,如果发现就直接返回,如果没有发现并不会直接加载,而是让自己的父类加载器去加载

等一下, 父类加载器会立即加载这个类么, 当然不是, 父类加载器也会采用同样的策略, 在自己的缓存中查找,如果没有找到, 就委托给自己的父类, 一直到Bootstrp loader

如果一直到Bootstrp loader 这一层仍然找不到这个类, classloader才会自己加载它

tomcat实际上采用了不同的类加载机制

9b01c7c8a58623a67c381f341e23549c.png

这里tomcat的Bootstrap实际上包含了jvm的Bootstrap和ExtClassLoader ($JAVA_HOME/jre/lib/ext), 加载了一些jvm最基本的类

System classloader 忽略系统本身的classpath, 加载

$CATALINA_HOME/bin/bootstrap.jar — Contains the main() method that is used to initialize the Tomcat server, and the class loader implementation classes it depends on.

$CATALINA_BASE/bin/tomcat-juli.jar or $CATALINA_HOME/bin/tomcat-juli.jar — Logging implementation classes. These include enhancement classes to java.util.logging API, known as Tomcat JULI, and a package-renamed copy of Apache Commons Logging library used internally by Tomcat. See logging documentation for more details.

If tomcat-juli.jar is present in $CATALINA_BASE/bin, it is used instead of the one in $CATALINA_HOME/bin. It is useful in certain logging configurations

$CATALINA_HOME/bin/commons-daemon.jar — The classes from Apache Commons Daemon project. This JAR file is not present in the CLASSPATH built by catalina.bat|.sh scripts, but is referenced from the manifest file of bootstrap.jar.

Common classloader 用于加载tomcat lib目录下的jar和class, 不要把webapp相关jar放在这里

unpacked classes and resources in $CATALINA_BASE/lib

JAR files in $CATALINA_BASE/lib

unpacked classes and resources in $CATALINA_HOME/lib

JAR files in $CATALINA_HOME/lib

一般来说,这个目录包含

annotations-api.jar — JavaEE annotations classes.

catalina.jar — Implementation of the Catalina servlet container portion of Tomcat.

catalina-ant.jar — Tomcat Catalina Ant tasks.

catalina-ha.jar — High availability package.

catalina-tribes.jar — Group communication package.

ecj-*.jar — Eclipse JDT Java compiler.

el-api.jar — EL 2.2 API.

jasper.jar — Tomcat Jasper JSP Compiler and Runtime.

jasper-el.jar — Tomcat Jasper EL implementation.

jsp-api.jar — JSP 2.2 API.

servlet-api.jar — Servlet 3.0 API.

tomcat-api.jar — Several interfaces defined by Tomcat.

tomcat-coyote.jar — Tomcat connectors and utility classes.

tomcat-dbcp.jar — Database connection pool implementation based on package-renamed copy of Apache Commons Pool and Apache Commons DBCP.

tomcat-i18n-**.jar — Optional JARs containing resource bundles for other languages. As default bundles are also included in each individual JAR, they can be safely removed if no internationalization of messages is needed.

tomcat-jdbc.jar — An alternative database connection pool implementation, known as Tomcat JDBC pool. See documentation for more details.

tomcat-util.jar — Common classes used by various components of Apache Tomcat.

tomcat7-websocket.jar — WebSocket 1.1 implementation

websocket-api.jar — WebSocket 1.1 API

下面重点来了

WebappX  加载器闪亮登场

WebappX — A class loader is created for each web application that is deployed in a single Tomcat instance. All unpacked classes and resources in the /WEB-INF/classes directory of your web application, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application, are made visible to this web application, but not to other ones.

也就是说, 每个webapp都会拥有一个独立的WebappX加载器, 它会加载/WEB-INF/classes和/WEB-INF/lib下的所有资源, 只对这个webapp可见,不共享给其他webapp

这个行为是基于 Servlet Specification, version 2.4, section 9.7.2 Web Application Classloader 有兴趣的朋友可以去读一下

WebappX  会先尝试自己加载需要的类,而不是使用父类委托模型委托给自己的父加载器, 但是这里有一些例外, JRE base classes不会被这个加载器处理,还有就是Servlet API classes也不会被这个加载器加载, 所以不要把这些例外放在自己的WEB-INF/lib文件夹里

默认的加载顺序是

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)

如果设置了 则加载顺序是

Bootstrap classes of your JVM

System class loader classes (described above)

Common class loader classes (described above)

/WEB-INF/classes of your web application

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

最后我要加入一个自己以往的经验

测试的时候如果需要在tomcat中放入同包同名的类(有时候为了测试方便,比如com.lizhe.Test在一个已经被部署的jar包里,但是测试的时候为了覆盖掉)

可以直接在classes文件夹里放入com.lizhe.Test.class 这个class会被优先加载

如果需要覆盖一个jar包, 比如test.jar,可以将新的jar包命名为aaaaa.jar , 因为根据实际测试, tomcat加载同路径下的jar包时会按照字母顺序排序,aaaaa.jar会优先于test.jar加载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值