类加载器与类的”相同“判断
类加载器除了用于加载类外,还可用于确定类在Java虚拟机中的唯一性。
不同类加载器加载的类在 JVM 看来是两个不同的类,因为在 JVM 中一个类的唯一标识是 类加载器+类名(包括包名)。
类加载器种类
启动类加载器,Bootstrap ClassLoader,加载JAVA_HOME\lib,或者被-Xbootclasspath参数限定的类
扩展类加载器,Extension ClassLoader,加载\lib\ext,或者被java.ext.dirs系统变量指定的类
应用程序类加载器,Application ClassLoader,加载ClassPath中的类库
自定义类加载器,通过继承ClassLoader实现,一般是加载我们的自定义类
双亲委派的关键源代码
JVM 在触发类加载时调用的是 ClassLoader.loadClass 方法。这个方法的实现了双亲委派:先检查指定类(应该仅是包名+类名,不包括类加载器)是否已经被加载过;
若否则递归调用父类加载器的loadClass()方法查询,(父类非指继承,而是指组合的parent变量);
若递归调用失败,就调用本ClassLoader的findClass()进行加载。
我:简单来说,若不想破坏双亲委派,则不要改loadClass()方法,只能改findClass()。
JAVA热部署
首先谈一下何为热部署(hotswap),热部署是在不重启 Java 虚拟机的前提下,能自动侦测到 class 文件的变化,更新运行时 class 的行为。
一种实现的方法是创建自己的 classloader 来加载需要监听的 class,这样就能控制类加载的时机,从而实现热部署:
1、销毁自定义classloader(被该加载器加载的class也会自动卸载);
2、更新class
3、使用新的ClassLoader去加载class
Tomcat独特的类加载机制1,2
tomcat为什么要使用自定义类加载器?
一个tomcat中可以部署多个应用,而每个应用中都存在很多类,并且各个应用中的类是独立的,全类名是可以相同的,比如一个博客系统中可能存在com.data.User类,一个库存系统中可能也存在com.data.User类。
一个tomcat,不管内部部署了多少应用,Tomcat启动之后就是一个Java进程,也就是一个JVM,所以如果Tomcat中只存在一个类加载器,比如默认的AppClassLoader,那么就只能加载一com.data.User类,这是有问题的 .
Tomcat如何实现自己独特的类加载机制?
Tomcat有多种类加载器。其中WebApp类加载器和Jsp类加载器通常会存在多个实例,每一个Web应用程序对应一个WebApp类加载器,每一个JSP文件对应一个Jsp类加载器:
WebappClassLoader是各个Webapp私有的类加载器,加载路径中的class只对当前Webapp可见。WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离。
而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能。
使用自定义类加载器解决JAR包多版本冲突问题3
症状:让sdk-1.0与sdk-2.0并存于项目,会导致如下状况:
解决:自定义classloader,使得两个版本的jar包使用两个不同的classloader,这样就可以实现多个同类但不同版本的jar包并存:
其它方案:1、微服务化,一个版本一个服务;2、shaded,参考本博----用shade打包来解决jar包冲突
附:
一些其他参考文章:
Java 类加载机制(阿里)-何时初始化类
知乎----如何实现Java类隔离加载?
-
头条:在tomcat中,为什么要使用自定义类加载器? ↩︎
-
深入理解 Tomcat(四)Tomcat 类加载器之为何违背双亲委派模型 ↩︎文章来源:https://www.toymoban.com/news/detail-515230.html
-
基于sofaark轻松实现不同版本jar包类隔离机制 ↩︎文章来源地址https://www.toymoban.com/news/detail-515230.html
到了这里,关于tomcat与自定义类加载器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!