Tomcat 的类加载机制

325 阅读4分钟

内容输出来源:拉勾教育Java高薪训练营

  • 什么是类的加载

我们知道,我们平时编写的代码要先经过编译,变成**.class字节码文件**,才能被JVM运行,那么**.class字节码文件被加载到JVM内存中的过程就叫做类的加载**。

想要搞清楚Tomcat的类加载机制,就要先弄明白JVM的类加载机制,因为Tomcat的类加载机制就是在JVM的类加载机制的基础上做了一些变动。

1. JVM的类加载机制

  • 类加载器(ClassLoader)

    在JVM的类加载机制中,**类加载器(ClassLoader)**是一个非常重要的角色,JVM内置了几种类加载器:引导类加载器拓展类加载器系统类加载器,他们之间是父子关系,可以形成树形结构。

类加载器作用
引导类加载器 BootStrapClassLoaderc++编写,用来加载Java核心类库java.*,如rt.jar中的类,构建ExtClassLoader和AppClassLoader
拓展类加载器 ExtClassLoaderjava编写,加载拓展库JAVA_HOME/lib/ext目录下的jar中的类,如classpath下的jre,javax.*或者java.ext.dir指定位置中的类
系统类加载器 SystemClassLoader/AppClassLoader默认的类加载器,搜索环境变量classpat中指明的路径

除此之外: ⽤户可以⾃定义类加载器(Java编写,⽤户⾃定义的类加载器,可加载指定路径的 class ⽂件)    当 JVM 运⾏过程中,⽤户⾃定义了类加载器去加载某些类时,会按照下⾯的步骤(⽗类委托机制)

  • 1)⽤户⾃⼰的类加载器,把加载请求传给⽗加载器,⽗加载器再传给其⽗加载器,⼀直到加载器 树的顶层
  • 2)最顶层的类加载器⾸先针对其特定的位置加载,如果加载不到就转交给⼦类
  • 3)如果⼀直到底层的类加载都没有加载到,那么就会抛出异常 ClassNotFoundException 因此,按照这个过程可以想到,如果同样在 classpath 指定的⽬录中和⾃⼰⼯作⽬录中存放相同的 class,会优先加载 classpath ⽬录中的⽂件

2. 双亲委派机制

2.1. 什么是双亲委派机制?

当某个类加载器加载某个.class文件时,首先不自己加载,而是把任务委托给它的上级类加载器,递归这个操作,上级类加载器再委托给上级类加载器,直到类加载器树的顶层,如果上级的类加载器都没有加载这个类,再自己去加载。

2.2. 双亲委派机制的作用

  • 1)防止重复加载同一个.class,当要加载一个.class时,通过委托的方式向上级问一问,如果加载过了就不再加载。
  • 2)保证核心的.class文件不被篡改。通过委托的方式,不会篡改核心的.class,即使篡改了也不会被加载。(如果子类加载器先加载,那么我们可以自定义一些java.lang包中的基础类,然后通过自定义类加载器,从而篡改了原来的基础类。比如:自定义一个Object类,通过自定义类加载器加载,这样整个应用中真正的Object类就被篡改了)

3. Tomcat的类加载机制

Tomcat的类加载机制相对于 JVM 的类加载机制做了⼀些改变。 没有严格的遵从双亲委派机制,也可以说打破了双亲委派机制。

  • 引导类加载器扩展类加载器 的作⽤不变
  • 系统类加载器正常情况下加载的是 CLASSPATH 下的类,但是 Tomcat 的启动脚本并未使⽤该变量,⽽是加载tomcat启动的类,⽐如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin
  • Common 通⽤类加载器加载Tomcat使⽤以及应⽤通⽤的⼀些类,位于CATALINA_HOME/lib下,⽐如servlet-api.jar
  • Catalina ClassLoader ⽤于加载服务器内部可⻅类,这些类应⽤程序不能访问
  • Shared ClassLoader ⽤于加载应⽤程序共享类,这些类服务器不会依赖
  • Webapp ClassLoader,每个应⽤程序都会有⼀个独⼀⽆⼆的Webapp ClassLoader,他⽤来加载 本应⽤程序 /WEB-INF/classes 和 /WEB-INF/lib 下的类。

tomcat 8.5 默认改变了严格的双亲委派机制

  • ⾸先从 Bootstrap Classloader加载指定的类
  • 如果未加载到,则从 /WEB-INF/classes加载
  • 如果未加载到,则从 /WEB-INF/lib/*.jar 加载
  • 如果未加载到,则依次从 System、Common、Shared 加载(在这最后⼀步,遵从双亲委派机制)