Tomcat打破双亲委派机制实现各应用程序的类库相互隔离原理与实现demo

news2024/11/17 3:57:05

1、实现原理


以Tomcat类加载为例,Tomcat 如果使用默认的双亲委派类加载机制行不行?
我们思考一下:Tomcat是个web容器, 那么它要解决什么问题:
1. 一个web容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的
不同版本,不能要求同一个类库在同一个服务器只有一份,因此要保证每个应用程序的类库都是
独立的,保证相互隔离。
2. 部署在同一个web容器中相同的类库相同的版本可以共享。否则,如果服务器有10个应用程
序,那么要有10份相同的类库加载进虚拟机。
3. web容器也有自己依赖的类库,不能与应用程序的类库混淆。基于安全考虑,应该让容器的
类库和程序的类库隔离开来。
4. web容器要支持jsp的修改,我们知道,jsp 文件最终也是要编译成class文件才能在虚拟机中
运行,但程序运行后修改jsp已经是司空见惯的事情, web容器需要支持 jsp 修改后不用重启。


2、tomcat的几个主要类加载器


commonLoader:Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容
器本身以及各个Webapp访问;
catalinaLoader:Tomcat容器私有的类加载器,加载路径中的class对于Webapp不
可见;
sharedLoader:各个Webapp共享的类加载器,加载路径中的class对于所有
Webapp可见,但是对于Tomcat容器不可见;
WebappClassLoader:各个Webapp私有的类加载器,加载路径中的class只对当前
Webapp可见,比如加载war包里相关的类,每个war包应用都有自己的
WebappClassLoader,实现相互隔离,比如不同war包应用引入了不同的spring版本,
这样实现就能加载各自的spring版本;

注意:
同一个JVM内,两个相同包名和类名的类对象可以共存,因为他们的类加载器可以不一
样,所以看两个类对象是否是同一个,除了看类的包名和类名是否都相同之外,还需要他们的类
加载器也是同一个才能认为他们是同一个。
 

3、JavaDemo

/**
 * @author WuSong
 * @version 1.0
 * @date 2022/12/7 16:59
 * @description
 */
public class MyTomcatClassLoader {

    static class TomcatClassLoader extends ClassLoader {
        private String classPath;

        public TomcatClassLoader(String classPath) {
            this.classPath = classPath;
        }

        private byte[] loadByte(String name) throws Exception {
            name = name.replaceAll("\\.", "/");
            FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
            int len = fis.available();
            byte[] data = new byte[len];
            fis.read(data);
            fis.close();
            return data;
        }

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            try {

                byte[] data = loadByte(name);
                return defineClass(name, data, 0, data.length);
            } catch (Exception e) {
                e.printStackTrace();
                throw new ClassNotFoundException();
            }
        }

        /**
         * 重写类加载方法,实现自己的加载逻辑,不委派给双亲加载
         * @param name
         * @param resolve
         * @return
         * @throws ClassNotFoundException
         */
        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            synchronized (getClassLoadingLock(name)){
                // 首先,检查类是否已加载
                Class<?> c = findLoadedClass(name);

                if(c == null){
                    // 如果仍然找不到,则按顺序调用findClass
                    // to find the class.
                    long t0 = System.nanoTime();
                    long t1 = System.nanoTime();

                    // TODO 核心改动点:非自定义的类还是走双亲委派加载
                    if(!name.startsWith("com.wusong.jvm")){
                        c = this.getParent().loadClass(name);
                    }else{
                        c = findClass(name);
                    }

                    // 定义类加载器;记录统计数据
                    PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    PerfCounter.getFindClasses().increment();
                }

                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }


    }


    public static void main(String[] args) throws Exception {

        TomcatClassLoader classLoader = new TomcatClassLoader("D:/test");
        // java文件的本地目录:D:/test/com/wusong/jvm/User.java
        Class clazz = classLoader.loadClass("com.wusong.jvm.User");
        Object obj = (Object) clazz.newInstance();
        Method method = clazz.getDeclaredMethod("sout", null);
        method.invoke(obj, null);
        System.out.println(clazz.getClassLoader().getClass().getName());

        TomcatClassLoader classLoader2 = new TomcatClassLoader("D:/test1");
        // java文件的本地目录:D:/test/com/wusong/jvm/User.java
        Class clazz2 = classLoader2.loadClass("com.wusong.jvm.User");
        Object obj2 = (Object) clazz2.newInstance();
        Method method2 = clazz2.getDeclaredMethod("sout", null);
        method2.invoke(obj2, null);
        System.out.println(clazz2.getClassLoader().getClass().getName());

    }

}

4、运行结果

可以看到最终的运行结果,类路径是同一个:com.wusong.jvm.User,但是读取出来是不同的类,这样就实现了相互隔离的效果

5、总结

tomcat就是利用了打破双亲委派机制,让运行在tomcat里面的war包、jar包的相同类目不同版本的类的相互隔离,和相同版本相同类的共享

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/70727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++对const引用的特殊处理、为什么函数形参的引用建议加上const?只是为了防止值被修改吗?

前言&#xff1a;我们知道普通变量、指针、函数形参&#xff0c;加上const修饰表示不可改变&#xff0c;但是引用前面加上const就有特别之处了 目录 const日常使用 const引用的特别处理 const引用创建临时变量规则 引用形参声明为const的三个理由 const日常使用 我们知道如…

resnet(2)------看看卷积

文章目录1 . 人脑是怎么认识到物体的2. 卷积3. 卷积核1 . 人脑是怎么认识到物体的 在谈卷积之前&#xff0c;我们先来了解一下人是怎么认识物体的。 人脑是个非常复杂的结构&#xff0c;是由无数个神经元连接起来&#xff0c;每个神经元都有自己负责记忆的东西。当人眼看到物体…

关于自增约束auto_increment需要注意的地方,mysql8版本的报错

目录一&#xff0c;自增约束auto_increment需要注意的地方附&#xff1a;就算插入数据失败&#xff0c;也进行自增&#xff1a;二&#xff0c;自增约束auto_increment在MySQL8版本的报错&#xff1a;一&#xff0c;自增约束auto_increment需要注意的地方 1 创建数据库表class&…

Logistic回归

通常&#xff0c;Logistic回归用于二分类问题&#xff0c;例如预测明天是否会下雨。当然它也可以用于多分类问题. Logistic回归是分类方法&#xff0c;它利用的是Sigmoid函数阈值在[0,1]这个特性。Logistic回归进行分类的主要思想是&#xff1a;根据现有数据对分类边界线建立回…

啊?我这手速也太差了吧?——C++Easyx“挑战六秒”小游戏

&#x1f411;本文作者&#xff1a;C橙羊&#x1f411; &#x1f3ae;&#x1f50a;本文代码适合编译环境&#xff1a;DEV-C&#x1f4bb; ✨&#x1f9e8;温馨提示&#xff1a;此文转载于codebus&#x1f389;&#x1f3a0; 最近橙羊在Easyx官网的codebus里随便逛逛的时候&am…

SpringMVC从入门到精通(一)

文章目录1. SpringMVC基本概念1.1 三层架构1.2 MVC架构1.3 什么是SpringMVC1.4 SpringMVC的优势2. SpringMVC 的入门2.1 入门程序2.2 SpringMVC执行原理刨析2.3 SpringMVC的核心执行流程2.4 SpringMVC的组件3. RequestMapping注解4.请求参数绑定4.1 参数绑定4.2 请求参数乱码问…

磨金石摄影技能干货分享|优秀纪实摄影作品欣赏—北京记事

1、蜂窝煤 三名青年男子踏着三轮车拉着满满一车蜂窝煤。脸上流露出清澈的笑容。这是九十年代的北京&#xff0c;背后的天安门格外的显眼。那时候处于改革开放的初期&#xff0c;虽然还不是很富裕&#xff0c;但大家脸上洋溢着幸福与希望的笑容。 蜂窝煤是冬天必备&#xff0c;九…

【强化学习论文合集】十一.2018国际表征学习大会论文(ICLR2018)

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。 本专栏整理了近几年国际顶级会议中,涉及强化学习(Rein…

历届青少年蓝桥杯python编程选拔赛 STEMA评测比赛真题解析【持续更新 已更新至34题】

蓝桥杯python选拔赛真题 历届青少年蓝桥杯python编程选拔赛真题解析 选拔赛 真题34-回文数升级 【蓝桥杯选拔赛真题34】python回文数升级 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析_小兔子编程的博客-CSDN博客python回文数升级2020年青少年组python蓝桥杯选拔赛真题一、…

剑指Offer39——数组中出现次数超过一半的数字

摘要 剑指Offer39 数组中出现次数超过一半的数字 本题常见的三种解法&#xff1a; 哈希表统计法&#xff1a; 遍历数组 nums &#xff0c;用 HashMap 统计各数字的数量&#xff0c;即可找出 众数 。此方法时间和空间复杂度均为 O(N) 。数组排序法&#xff1a; 将数组 nums 排…

Python学习-8.1.1 标准库(time库的基础与实例)

2.1 time库 time库是Python提供的处理时间标准库。time库提供系统级精确计时器的计时功能&#xff0c;可以用来分析程序性能&#xff0c;也可以让程序暂停运行时间。 2.1.1 时间处理函数 time.time()函数&#xff1a;获取当前时间戳。 代表着如今的时间与1970年1月1日0分0秒…

18.10 字节码指令集与解析举例 - 同步控制指令

同步控制指令 组成 java虚拟机支持两种同步结构&#xff1a;方法级的同步和方法内部一段指令序列的同步&#xff0c;这两种同步都是使用monitor来支持的。 方法级的同步 方法级的同步&#xff1a;是隐式的&#xff0c;即无须通过字节码指令来控制&#xff0c;它实现在方法调…

Java+SSM网上书城全套含微信支付电商购物(含源码+论文+答辩PPT等)

项目功能简介: 本项目含代码详细讲解视频&#xff0c;手把手带同学们敲代码从0到1完成项目 该项目采用技术Springmvc、Spring、MyBatis、Tomcat服务器、MySQL数据库 项目含有源码、配套开发软件、软件安装教程、项目发布教程以及代码讲解教程 项目功能介绍&#xff1a; 系统管理…

HTML做一个简单的页面(纯html代码)地球专题学习网站

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

STM32F4 | 新建工程模板——寄存器版本 | HAL库入门 | 新建工程模板——库函数版本

文章目录一、新建工程模板——寄存器版本二、HAL入门1.固件库和寄存器的区别2.STM32CubeF43.HAL库包介绍三、新建HAL库工程模板一、新建工程模板——寄存器版本 开发环境&#xff1a;MDK5软件包&#xff1a;STM32CubeF4包 新建工程模板的一般步骤为&#xff1a; 新建工程目录&a…

【UE5】多用户协同编辑

UE5新出了一个多用户协同功能所以想搭一个来玩玩。 Epic已经将流程极度的简化了&#xff0c;在B站虚幻官方也放出了教程视频&#xff0c;[官方文档](多用户编辑入门 | 虚幻引擎文档 (unrealengine.com))也有教程。 这里做一下简要记录。 1.启用插件 首先打开Multi-User Edi…

SoftPerfect NetWorx中管理流量和宽带设备工具

SoftPerfect NetWorx中管理流量和宽带设备工具 NetWorx是用于在Windows中管理流量和宽带设备的简单工具和实用程序。如果我们利用交通设施&#xff0c;毫不拖延地利用教育系统&#xff0c;以及与各种驾驶员相关的学习&#xff0c;那么当加载互联网时&#xff0c;通过软件秘密使…

[附源码]计算机毕业设计酒店客房管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

BaiqiSoft MstHtmlEditor for .NET负责编辑的控制器

BaiqiSoft MstHtmlEditor for .NET负责编辑的控制器 BaiqiSoft MstHtmlEditor获取.NET for win表单被认为是一个元素,用户可以轻松灵活地将其融入到C#、VB.NET甚至WPF软件中。负责编辑的控制器,.NET Win Forms的MstHtmlEditor,允许用户和开发人员,甚至非技术用户使用该系列…

Docker入门第二期

写目一、宿主机与容器之间的文件拷贝二、数据卷三、数据卷容器四、Dockerfile一、宿主机与容器之间的文件拷贝 docker run -p 3307:3306 --name mysql1 -di -v /home/javaxl/data/mysql/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /home/javaxl/data/mysql/data/:/var/lib/…