首页 > 其他分享 >Tomcat中为什么要使用自定义类加载器

Tomcat中为什么要使用自定义类加载器

时间:2024-05-13 11:09:39浏览次数:17  
标签:Web name parent ClassLoader Tomcat 加载 自定义

Tomcat 使用自定义类加载器主要是基于以下几个关键原因:

1.应用隔离:Tomcat作为一个Web容器,能够同时部署和运行多个Web应用程序。每个应用可能依赖不同的库版本或者包含同名类,为了确保每个应用的类库相互独立,避免类冲突,Tomcat 为每个Web应用提供了一个独立的类加载器实例,即`WebAppClassLoader`。这样,即使不同应用中存在相同的类名,它们也是被各自的应用类加载器加载,互不影响。

2.热部署与热替换:自定义类加载器支持热部署和类的热替换功能。当Web应用发生变化时,不需要重启整个Tomcat服务器,只需重新加载对应的Web应用即可。通过创建新的类加载器来加载更新后的类,旧的类加载器和旧的类可以被垃圾回收,实现类的平滑升级。

3.遵循Servlet规范:Servlet规范要求Web容器必须为每个Web应用提供独立的类加载器上下文,以满足应用的独立性和安全性需求。Tomcat的自定义类加载器体系结构正是对这一规范的实现。

4. 层次化加载机制:Tomcat的类加载器体系采用分层设计,包括但不限于以下几个关键的类加载器:


   - Bootstrap ClassLoader:负责加载JDK核心类库。
   - Common/Shared ClassLoader:加载Tomcat和所有Web应用共享的类库。
   - Catalina ClassLoader:加载Tomcat自身的类。
   - WebApp ClassLoader:为每个Web应用创建,负责加载该应用特有的类和库。
   

// 自定义类加载器的基类,模仿Tomcat中类加载器的委托逻辑
abstract class CustomClassLoader extends ClassLoader {
    protected ClassLoader parent; // 父加载器引用

protected CustomClassLoader(ClassLoader parent) {
        super(parent);
        this.parent = parent;
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // Delegate to the parent class loader if not found
c = super.loadClass(name, false); // 正确的调用方式
} catch (ClassNotFoundException e) {
                    // If still not found, then invoke findClass in this class loader
c = findClass(name);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    // 抽象方法,子类需实现以定义如何查找类
protected abstract Class<?> findClass(String name) throws ClassNotFoundException;
}
// 模拟TomcatCommonClassLoader
class CommonClassLoader extends CustomClassLoader {
    public CommonClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        System.out.println("CommonClassLoader wei");
        // 实现查找共享类的逻辑
throw new ClassNotFoundException("Not implemented wei");
    }
}
// 自定义类加载器的基类,模仿Tomcat中类加载器的委托逻辑
abstract class CustomClassLoader extends ClassLoader {
    protected ClassLoader parent; // 父加载器引用

protected CustomClassLoader(ClassLoader parent) {
        super(parent);
        this.parent = parent;
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // Delegate to the parent class loader if not found
c = super.loadClass(name, false); // 正确的调用方式
} catch (ClassNotFoundException e) {
                    // If still not found, then invoke findClass in this class loader
c = findClass(name);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    // 抽象方法,子类需实现以定义如何查找类
protected abstract Class<?> findClass(String name) throws ClassNotFoundException;
}

上面三段代码分别是:一个基础的,模拟Tomcat中通用的加载逻辑;一个,代表Tomcat中用于加载共享类库的类加载器;以及一个,模拟每个Web应用独有的类加载器。在方法中,我们展示了如何通过Web应用类加载器加载类,同时这个加载器会委托给共享类加载器,模拟了Tomcat类加载的委托机制。

这种层次结构允许类加载器首先在本地查找类,找不到时再委托给父加载器,既保证了类加载的高效性,又确保了类的正确加载顺序,避免了类覆盖问题。

标签:Web,name,parent,ClassLoader,Tomcat,加载,自定义
From: https://www.cnblogs.com/2324hh/p/18188818

相关文章

  • SQL Server实战七:自定义数据类型、标量值、内嵌表值、多语句表值函数的操作
      本文介绍基于MicrosoftSQLServer软件,实现数据库用户自定义数据类型的创建、使用与删除,以及标量值、内嵌表值、多语句表值函数等用户定义函数的创建、使用、删除方法。目录1用SQL语句创建一个用户定义的数据类型Idnum2使用Idnum创建学生表STUDENT与教师表TEACHER3交互式......
  • axios无法加载响应数据:no data found for resource with given identifier
    做一个demo,springboot写好了接口,postman请求也没问题,如下:但是axios请求时,却发生了问题:查了一圈,没发现啥问题,又想起来看下控制台信息跨域的问题?网上也有这么说的,抱着试试的态度在controller上增加了跨域的注解@CrossOrigin重新运行,页面刷新,ok~......
  • MyBatis延迟加载
    MyBatis是否支持延迟加载延迟加载的意思是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。MyBatis支持一对一关联对象和一对多关联集合对象的延迟加载。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=truel/false,默认是关闭的。或者fetchType=laz......
  • springboot内嵌tomcat的实现原理
    目录一、tomcat运行原理的简单分析1.1Coyote1.2容器catalina二、用编码的方式启动tomcat一、tomcat运行原理的简单分析tomcat运行时可以简单分成两个大的模块,(1)负责处理socket连接并转换成request对象的部分,连接器Coyote(2)处理用户的请求的容器Catalina下面简单介绍......
  • 自定义函数在LCD上显示一张不超过LCD像素大小的色深为 24bit的bmp图片
    设计程序实现在LCD上任意位置显示一张任意大小的色深为24bit的bmp图片,要求图像不失真可以在开发板的LCD上显示。头文件包含#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<sys/mman.h>#include<linux/......
  • 一个低级问题导致vLLM加载大模型时ray卡死
    这两天一直被一个问题困扰,用vLLM加载千问时不能开并行(tensor_parallel_size>1),一开就会卡在ray阶段,最初是提示StartedalocalRayinstance,后来手工启动ray集群,就提示connectedtoRaycluster。无论怎样调都无法跑下去,根本不会加载模型,换了各种版本的vllm、transformer、ray......
  • 自定义各类基础排序算法
    接口函数基础信息/********************************************************************* 文件名称: 数据结构中对于无序数列的排序算法* 文件作者:[email protected]* 创建日期:2024/05/11* 文件功能:对无序数列进行排序* 注意事项:None** C......
  • Blazor WebAssembly使用 AuthenticationStateProvider 自定义身份认证
    本文章以客户端基础,实现类似后台系统,进入后台控制台页面需要经过登录身份验证才可访问情况简单来时就是实现前后端分离,前端通过token和用户信息进行身份认证,或者在 AuthenticationStateProvider 实现方法 GetAuthenticationStateAsync 中调用后台接口进行身份验证安装依......
  • 从零手写实现 tomcat-11-filter 过滤器
    创作缘由平时使用tomcat等web服务器不可谓不多,但是一直一知半解。于是想着自己实现一个简单版本,学习一下tomcat的精髓。系列教程从零手写实现apacheTomcat-01-入门介绍从零手写实现apacheTomcat-02-web.xml入门详细介绍从零手写实现tomcat-03-基本的socket实......
  • dotnet 使用自定义特性
    namespaceTETTD.Common{///<summary>///导入excel特性标记字段映射的列///</summary>[AttributeUsage(AttributeTargets.Property|AttributeTargets.Field,AllowMultiple=false)]publicclassReadAttribute:Attribute{p......