JVM-类加载器

2021-08-19  本文已影响0人  甜甜起司猫_

JVM-类加载器

类与类加载器

对于类与类加载器有两种限定:

  1. 对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性
  2. 每一个类加载器,都拥有一个独立的类名称空间

基于以上两点总结出:

比较两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义

这一结论是后面双亲委派模型的基础

双亲委派模型

对于JVM来说,有两种类加载器:

  1. 启动类加载器Bootstrap ClassLoader
  2. 所有其他的类加载器

以上类加载器全部继承自ClassLoader

还可以划分的更细致:

  1. 启动类加载器Bootstrap ClassLoader
  2. 扩展类加载器Extension ClassLoader
  3. 应用程序类加载器Application ClassLoader

启动类加载器Bootstrap ClassLoader

启动类加载器Bootstrap ClassLoader负责将存放在<JAVA_HOME>\lib目录中、或者-Xbootclasspath参数所指定的路径中的类库加载到虚拟机中。

启动类加载器无法直接被引用,如果需要启动类加载器去加载,直接返回null即可。

扩展类加载器Extension ClassLoader

负责加载<JAVA_HOME>\lib\ext目录中的、或者被java.ext.dirs系统变量所指定的路径中的所有的类库。

应用程序类加载器Application ClassLoader

负责加载用户类路径ClassPath上所指定的类库

双亲委派模型的工作过程

一个类加载器收到类加载的请求:

  1. 把这个请求委派给父类加载器去完成
  2. 当父加载器反馈无法完成这个加载请求,子加载器才会尝试自己去加载

双亲委派模型的好处

  1. 所有类加载器的组成带有优先级的层次关系
  2. 保证所有类在各种类加载器环境中都是同一个类

破坏双亲委派模型

  1. SPI
  2. 热部署
  3. tomcat

tomcat为什么要破坏双亲委派

上面提到双亲委派的其中一个好处是:保证所有类在各种类加载器环境中都是同一个类。

而在tomcat中,每个容器中的应用所使用的类库版本是不一定相同的。为了达到容器坚类库隔离的目的,就和上述特性冲突了,所以需要破坏这个双亲委派机制,tomcat自己实现了类加载器去做容器间类库的隔离:

tomcat类加载过程

tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。具体的加载逻辑位于WebAppClassLoaderBase.loadClass()方法中:

  1. 先在本地缓存中查找是否已经加载过该类(对于一些已经加载了的类,会被缓存在resourceEntries这个数据结构中),如果已经加载即返回,否则 继续下一步。
  2. 让系统类加载器(AppClassLoader)尝试加载该类,主要是为了防止一些基础类会被web中的类覆盖,如果加载到即返回,返回继续。
  3. 前两步均没加载到目标类,那么web应用的类加载器将自行加载,如果加载到则返回,否则继续下一步。
  4. 最后还是加载不到的话,则委托父类加载器(Common ClassLoader)去加载。
上一篇下一篇

猜你喜欢

热点阅读