今天下午被同事问到如果我有两个不同版本的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实际上采用了不同的类加载机制

这里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加载

tomcat java.ext.dirs_tomcat classloader 加载class顺序相关推荐

  1. Java的ClassLoader加载是怎么保证安全的?

    点击上方蓝色字体,选择"标星公众号" 优质文章,第一时间送达 1.类加载机制 Java中的源码.java后缀文件会在运行前被编译成.class后缀文件,文件内的字节码的本质就是一个 ...

  2. 图解classloader加载class的流程及自定义ClassLoader

    http://longdick.iteye.com/blog/442213 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有B ...

  3. java加载并运行虚拟机_《深入理解Java虚拟机》- Java虚拟机是如何加载Java类的?...

    Java虚拟机是如何加载Java类的?  这个问题也就是面试常问到的Java类加载机制.在年初面试百战之后,菜鸟喜鹊也是能把这流程倒背如流啊!但是,也只是字面上的背诵,根本就是像上学时背书考试一样. ...

  4. java 线程加载类_怎么判断java当前线程是否加载了一个类的字节码

    展开全部 原生的ClassLoader是有e68a843231313335323631343130323136353331333337616631一个方法判断类是否已经加载的/** * Returns ...

  5. 自定義 ForkJoinPool 線程池,并消除classLoader加载失败的问题

    自定義 ForkJoinPool 線程池,并消除classLoader加载失败的问题 添加 setContextClassLoader 写入classLoader 信息 import java.uti ...

  6. java打印已经被加载的类_使用URLClassLoader加载类,不会报错,但被加载类中的内容也没有打印出来...

    被加载类和加载类的程序在一个文件夹下: 运行没有任何结果: D:java_exercise>javac URLTest.java D:java_exercise>java URLTest ...

  7. Java 单例模式:懒加载(延迟加载)和即时加载

    Java 单例模式:懒加载(延迟加载)和即时加载 引言 在开发中,如果某个实例的创建需要消耗很多系统资源,那么我们通常会使用惰性加载机制(或懒加载.延时加载),也就是说只有当使用到这个实例的时候才会创 ...

  8. Java反射-静态/动态加载类

    title: Java反射-静态/动态加载类 date: 2019-05-28 18:50:00Java反射-静态/动态加载类 Class 类是对象,是java.lang.Class类的实例对象.任何 ...

  9. 使用java concurrent处理异步加载图片功能

    转载:http://marshal.easymorse.com/archives/3081 java5开始,增加了concurrent api,用于并发处理.比如起多个线程并发从网络上下载图片,然后在 ...

  10. ClassLoader加载类时序图及Qzon修复流程图

    很少画UML时序图,有点难顶 ClassLoader加载类时序图,parent.loadClass()处为循环,不知道这样画对不对 Qzon修复流程图

最新文章

  1. 面试:InnoDB 中一棵 B+ 树可以存放多少行数据?
  2. beanstalkd php扩展,PHP操作Beanstalkd队列(1)安装与基础
  3. mybatis 配置
  4. 【收藏】机器学习入门的常见问题集(文末送书)
  5. 链表笔试题汇编(一)
  6. 【程序设计】程序错误类型
  7. js深拷贝和浅拷贝对数组的影响_JS基础——深拷贝与浅拷贝
  8. android 8.0 edittext,关注TextInputEditText的Android 8.0 Oreo崩溃
  9. 建立RHELAS4下面的Yum本地源
  10. 5.深入分布式缓存:从原理到实践 --- 从Memcached开始了解集中式缓存
  11. 有道词典java下载电脑版下载手机版下载安装_【有道词典官方下载】有道词典PC版下载_多特软件站...
  12. sql server 2008导出数据至Excel或者wps
  13. 极域电子书包教师端程序启动介绍
  14. Github删除历史提交记录的方法
  15. 赴日本护师研修生项目介绍
  16. [洛谷多校第三场] T176282 Mana Eel‘s Problem [分段前缀积]
  17. 精灵随着鼠标的移动而移动
  18. 深度Linux 安装英伟达闭源驱动,deepin20 安装英伟达闭源驱动的步骤详解
  19. 08——驾校科目一考试——布局按钮
  20. sqrt函数模拟实现的两种方法

热门文章

  1. 「转发领抱枕」40万奖金等你来挑战!阿里云ECS Cloudbuild开发者大赛重磅开启
  2. 阿里云无影云电脑千万级补贴,助力广东企业居家办公
  3. 招聘云计算、虚拟化、前端开发、测试等工程师
  4. 图像下采样 matlab_MATLAB--数字图像处理 图像的采样与量化
  5. 【心电信号】基于matlab心电信号采集与处理【含Matlab源码 954期】
  6. 【缺陷检测】基于matlab形态学水果蔬菜缺陷检测【含Matlab源码 820期】
  7. python中单词个数_python 统计单词个数
  8. windows7局域网传输到mac_计算机三级网络技术(5):局域网技术基础及应用
  9. 树莓派开发界面显示温度_关于树莓派linux开发板
  10. 例2.12 今年暑假不AC - 九度教程第22题(贪心算法)