Tomcat 类加载机制剖析

Java类(java)一>字节码文件(class)一>字节码文件需要被加载到jvm内存当中(这个过程就是一个类加载的过程)
类加载器(ClassLoader,说白了也是一个类,jvm启动的时候先把类加载器读取到内存当中去,其他的类(比如各种jar中的字节码文件,自己开发的代码编译之后的.class文件等等))
要说 Tomcat的类加载机制,首先需要来看看Jvm的类加载机制,因为 Tomcat类加载机制是在Jvm类加载机制基础之上进行了一些变动。

JVM 的类加载机制

VM的类加载机制中有一个非常重要的角色叫做类加载器(ClassLoader),类加载器有自己的体系,Jvm内置了几种类加载器,包括∶引导类加载器、扩展类加载器、系统类加载器,他们之间形成父子关系,通过Parent 属性来定义这种关系,最终可以形成树形结构。




另外∶用户可以自定义类加载器Java编写,用户自定义的类加载器,可加载指定路径的class文件)

当JVM运行过程中,用户自定义了类加载器去加载某些类时,会按照下面的步骤(父类委托机制)
1)用户自己的类加载器,把加载请求传给父加载器,父加载器再传给其父加载器,一直到加载器树的顶层
2)最顶层的类加载器首先针对其特定的位置加载,如果加载不到就转交给子类
3)如果一直到底层的类加载都没有加载到,那么就会抛出异常ClassNotFoundException

因此,按照这个过程可以想到,如果同样在 classpath 指定的目录中和自己工作目录中存放相同的class,会优先加载 classpath 目录中的文件

双亲委派机制

什么是双亲委派机制

当某个类加载器需要加载某个.cass文件时,它首先把这个任务委托给他的上级类加载器,,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。

双亲委派机制的作用
  • 防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
  • 保证核心.class不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个.class对象。这样保证了class执行安全(如果子类加载器先加载,那么我们可以写一些与java.lang包中基础类同名的类,然后再定义一个子类加载器,这样整个应用使用的基础类就都变成我们自己定义的类了。
    Object类-一>自定义类加载器(会出现问题的,那么真正的Object类就可能被篡改了)

Tomcat 的类加载机制

Tomcat的类加载机制相对于Jvm的类加载机制做了一些改变。
没有严格的遵从双亲委派机制,也可以说打破了双亲委派机制
比如∶有一个tomcat,webapps下部署了两个应用
app1lib/a-1.0.jar com.lagou.edu.Abc
app2/lib/a-2.0,jar com. lagou.edu.Abc
不同版本中Abc类的内容是不同的,代码是不一样的


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

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

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

你可能感兴趣的:(Tomcat 类加载机制剖析)