面试——类加载(Tomcat,Spring,Java)

Java类加载

Java类加载的时机

一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载 (Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化 (Initialization)、使用(Using)和卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称 为连接(Linking)。
面试——类加载(Tomcat,Spring,Java)_第1张图片
Java——双亲委派机制(总是由父类先加载类,如果父类加载不了,才有子类加载)
面试——类加载(Tomcat,Spring,Java)_第2张图片
三次破坏加载;1.自定义类加载器,重写loadClass方法;2.使用线程上下文类加载器;

Tomcat类加载

Tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。

面试——类加载(Tomcat,Spring,Java)_第3张图片
Tomcat 不遵循双亲委派机制,那么如果我自己定义一个恶意的HashMap,会不会有风险呢?(面试官问)

答:显然不会有风险, tomcat不遵循双亲委派机制,只是自定义的classLoader顺序不同,但顶层还是相同的,还是要去顶层请求classloader

Tomcat的类加载
面试——类加载(Tomcat,Spring,Java)_第4张图片
1 Bootstrap 引导类加载器
加载JVM启动所需的类,以及标准扩展类(位于jre/lib/ext下)

2 System 系统类加载器
加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin下。

3 Common 通用类加载器
加载tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下,比如servlet-api.jar

4 webapp 应用类加载器
每个应用在部署后,都会创建一个唯一的类加载器。该类加载器会加载位于 WEB-INF/lib下的jar文件中的class 和 WEB-INF/classes下的class文件

当应用需要到某个类时,则会按照下面的顺序进行类加载:

1 使用bootstrap引导类加载器加载

2 使用system系统类加载器加载

3 使用应用类加载器在WEB-INF/classes中加载

4 使用应用类加载器在WEB-INF/lib中加载

5 使用common类加载器在CATALINA_HOME/lib中加载

通过对上面tomcat类加载机制的理解,就不难明白 为什么java文件放在Eclipse中的src文件夹下会优先jar包中的class?

这是因为Eclipse中的src文件夹中的文件java以及webContent中的JSP都会在tomcat启动时,被编译成class文件放在 WEB-INF/class 中。

而Eclipse外部引用的jar包,则相当于放在 WEB-INF/lib 中。因此肯定是 java文件或者JSP文件编译出的class优先加载。

Spring类加载

OverridingClassLoader 是 Spring 自定义的类加载器,默认会先自己加载(excludedPackages 或 excludedClasses 例外),只有加载不到才会委托给双亲加载,这就破坏了 JDK 的双亲委派模式。

参考博客:
https://blog.csdn.net/qq_46728644/article/details/122597773
https://blog.csdn.net/sinat_34976604/article/details/86709870
https://www.cnblogs.com/binarylei/p/10312531.html

你可能感兴趣的:(面试,java,tomcat,spring)