首页 > 其他分享 >【JVM】Tomcat 的类加载机制

【JVM】Tomcat 的类加载机制

时间:2024-06-22 20:00:05浏览次数:10  
标签:类库 Web Tomcat ClassLoader 委派 JVM 加载

Tomcat 是一个开源的 Java Servlet 容器,用于运行 Java Web 应用程序。它的类加载机制相对复杂,因为它需要在支持多种应用的同时保持隔离性和灵活性。以下是 Tomcat 类加载机制的详细描述。

Tomcat 类加载器的层次结构

Tomcat 采用了一种层次化的类加载器结构,以便在不同的应用程序之间实现类加载的隔离,同时也允许共享一些公共类库。Tomcat 的类加载器层次结构如下:

  1. Bootstrap ClassLoader

    • 这是 JVM 自带的类加载器,负责加载 Java 核心类库(如 rt.jar)。
  2. System ClassLoader

    • 也称为应用程序类加载器,加载 $JAVA_HOME/lib/extclasspath 中的类。
  3. Common ClassLoader

    • 由 Tomcat 自定义,加载 CATALINA_HOME/libCATALINA_BASE/lib 中的类库。
  4. Catalina ClassLoader

    • 加载 CATALINA_HOME/libCATALINA_BASE/lib 中的类库,通常与 Common ClassLoader 合并使用。
  5. Shared ClassLoader

    • 加载 CATALINA_BASE/shared/lib 中的类库,可供所有 Web 应用程序共享。
  6. Webapp ClassLoader

    • 每个 Web 应用都有自己的类加载器,加载 WEB-INF/classesWEB-INF/lib 中的类库。Tomcat 为每个 Web 应用程序创建一个新的 Webapp ClassLoader 实例。

类加载过程

  1. Bootstrap ClassLoader 首先加载 Java 核心类库。
  2. System ClassLoader 加载系统级别的类库。
  3. Common ClassLoader 加载 Tomcat 公共库。
  4. Catalina ClassLoader 加载与 Tomcat 运行时相关的类库。
  5. Shared ClassLoader 加载所有 Web 应用程序共享的类库。
  6. Webapp ClassLoader 最后加载各自应用程序的类库。此类加载器是独立的,确保不同 Web 应用程序之间的类隔离。

Webapp ClassLoader 的双亲委派模型

Webapp ClassLoader 使用双亲委派模型,但其委派顺序有所不同。一般的双亲委派模型是:子 -> 父 -> 根。而 Tomcat 的 Webapp ClassLoader 的委派顺序是:子 -> 父 -> 共享 -> 公共 -> 根。这是为了确保 Web 应用程序首先加载自己的类,而不是公共类库中的类。

典型的类加载顺序

当一个 Web 应用请求加载一个类时,Tomcat 的类加载器会按照以下顺序尝试加载:

  1. Webapp ClassLoader:首先检查 Web 应用的 WEB-INF/classesWEB-INF/lib 中是否有该类。
  2. Shared ClassLoader:如果 Webapp ClassLoader 没有找到,则委派给 Shared ClassLoader。
  3. Common ClassLoader:如果 Shared ClassLoader 也没有找到,则委派给 Common ClassLoader。
  4. System ClassLoader:如果 Common ClassLoader 也没有找到,则委派给 System ClassLoader。
  5. Bootstrap ClassLoader:最后由 Bootstrap ClassLoader 尝试加载。

破坏双亲委派模型

在某些情况下,可能需要打破双亲委派模型,以实现某些特定的功能。Tomcat 提供了几种方式:

  1. 自定义类加载器:通过创建自定义的类加载器,可以在特定的类加载场景中打破双亲委派模型。
  2. 使用server.xml配置文件:可以在 server.xml 文件中配置 <Loader> 元素,自定义 Web 应用的类加载器行为。
  3. 在 Web 应用中显式地使用不同的类加载器:例如,通过使用 Thread.currentThread().getContextClassLoader() 来获取当前线程的类加载器,并在应用代码中显式地使用它加载类。

示例:自定义 Web 应用类加载器

以下是一个简单的自定义 Web 应用类加载器的示例,展示了如何在 Tomcat 中打破双亲委派模型:

package com.example;

import java.net.URL;
import java.net.URLClassLoader;

public class CustomWebappClassLoader extends URLClassLoader {
    
    public CustomWebappClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // 打破双亲委派模型,首先尝试加载自己定义的类
        synchronized (getClassLoadingLock(name)) {
            // 检查是否已经加载过该类
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // 尝试从当前类加载器中加载
                    c = findClass(name);
                } catch (ClassNotFoundException e) {
                    // 如果当前类加载器无法加载,则委派给父类加载器
                    c = super.loadClass(name, resolve);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
}

context.xmlserver.xml 中配置自定义类加载器:

<Context path="/myapp" docBase="webapps/myapp" reloadable="true">
    <Loader loaderClass="com.example.CustomWebappClassLoader"/>
</Context>

总结

Tomcat 的类加载机制通过层次化的类加载器结构和双亲委派模型,确保了类加载的隔离性和安全性。然而,在某些特殊情况下,可能需要打破双亲委派模型,以实现特定的功能或需求。通过自定义类加载器和配置文件,开发者可以灵活地控制类加载行为。

标签:类库,Web,Tomcat,ClassLoader,委派,JVM,加载
From: https://blog.csdn.net/hui_zai_/article/details/139710601

相关文章

  • three.js 第八节 - gltf加载器、解码器
    //@ts-nocheck//引入three.jsimport*asTHREEfrom'three'//导入轨道控制器import{OrbitControls}from'three/examples/jsm/controls/OrbitControls'//导入hdr加载器(专门加载hdr的)import{RGBELoader}from'three/examples/jsm/loaders/RGBELoad......
  • linux环境安装启动多个tomcat
    1.安装jdk如果安装完毕记录安装位置如果不记得了可以输入whichjava查找java文件的位置然后根据结果输入ls-irt/usr/bin/java在根据结果查询ls-lrt/etc/alternatives/java查询到java存放的位置/usr/java/jdk1.8.0_191-amd64/jre/bin/java之后编辑vietc/profil......
  • JVM 垃圾回收
    文章目录1.如何判断对象可回收引用计数法可达性分析算法2.五种引用强软弱虚终虚引用终引用软引用案例软引用_引用队列弱引用对象3.回收算法标记清除算法标记整理复制回收4.分代垃圾回收堆内存大致分为两块:分代垃圾回收怎么工作:GC相关参数分析5.垃圾回收器相关概念:......
  • JVM类加载器与双亲委派机制
    通过上一篇Java的类加载机制相信大家已经搞明白了整个类加载从触发时机,接着我们就来看下类加载器,因为类加载机制是有加载器实现的。 类加载器的分类启动类加载器BootstrapClassLoader是Java虚拟机(JVM)的一部分,它负责加载Java核心库,也就是JavaRuntimeEnvironment......
  • JVM常见问题
    文章目录1JVM组成1.1JVM由那些部分组成,运行流程是什么?1.2什么是程序计数器?1.3你能给我详细的介绍Java堆吗?元空间(MetaSpace)介绍1.4什么是虚拟机栈1.5堆和栈的区别1.6能不能解释一下方法区?1.5.1概述1.5.2常量池1.5.3运行时常量池1.7你听过直接内存吗?1.8......
  • 【MindSpore学习打卡】初学教程-04数据集 Dataset-使用MindSpore实现高效数据加载与预
    在深度学习的世界里,数据是模型训练的根基。高质量的数据输入不仅能提升模型的性能,还能加速训练过程。MindSpore提供了一个强大的数据引擎,通过数据集(Dataset)和数据变换(Transforms)实现高效的数据预处理。本文将详细介绍如何使用MindSpore加载和处理数据集,并通过具体的示例......
  • JVM内存区域
    目录一、程序计数器(线程私有)二、虚拟机栈(线程私有)三、堆(Heap-线程共享)-运行时数据区四、方法区/永久代(线程共享)五、本地方法区(线程私有)JVM内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区域【JAVA堆、方法区】、直接内存。......
  • CSharp: 未加载文件或程序集
    发布到IIS服务器提示错误:不能多个版本的同一DLL,虽是文件名不同,也是这个报错    未能加载文件或程序集“System.Runtime.CompilerServices.Unsafe,Version=4.0.4.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。找到的程序集清单定义与程......
  • 记录--单页面首屏优化,打包后大小减少64M,加载速度快了13.6秒
     ......
  • 玄机——第六章 流量特征分析-常见攻击事件 tomcat wp
    文章目录一、前言二、概览简介三、参考文章步骤(分析)步骤#1.1在web服务器上发现的可疑活动,流量分析会显示很多请求,这表明存在恶意的扫描行为,通过分析扫描的行为后提交攻击者IPflag格式:flag{ip},如:flag{127.0.0.1}步骤#1.2找到攻击者IP后请通过技术手段确定其所在地......