首页 > 其他分享 >Tomcat进阶篇

Tomcat进阶篇

时间:2025-01-18 19:30:03浏览次数:3  
标签:Web Tomcat 自定义 ClassLoader 进阶篇 父类 加载

目录

对应的输出结果一、聊聊ClassLoader的那些事儿

1.类加载器的过程

2.类加载器的分类

3.Bootstrap ClassLoader

4.Extension ClassLoader

5. 自定义类加载器

6. 双亲委派机制

Catalina为什么不new出来?

1.Web容器的特性

2.Tomcat类加载器结构

3. Tomcat的类加载器的继承结构

系列文章

资料下载和预览地址:


对应的输出结果一、聊聊ClassLoader的那些事儿

  我们要分析清楚Tomcat中的类加载器相关的内容之前我们还是需要把JVM中的类加载器给大家理清楚。

1.类加载器的过程

  类加载器的作用就是从文件系统或者网络中加载Class文件,至于他是否可以运行就不是ClassLoader的工作了。

2.类加载器的分类

  JVM中支持的类加载器有两种类型,分别是 引导类加载器【Bootstrap ClassLoader】和 自定义类加载器【User-Defined ClassLoader】

在Java虚拟机层面定义:所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。

可以通过源码看到对应的类加载器的继承关系

ExtClassLoader

AppClassLoader

通过具体的案例代码可以来看看类加载器的使用

public static void main(String[] args) {
        // 获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println("systemClassLoader = " + systemClassLoader);
        // 获取父类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println("parent = " + parent);
        // 继续获取上层的类加载器
        ClassLoader bootstrapClassLoader = parent.getParent();
        System.out.println("bootstrapClassLoader = " + bootstrapClassLoader);
        // 自定义Java类
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println("classLoader = " + classLoader);
        // Java系统类
        ClassLoader classLoader1 = String.class.getClassLoader();
        System.out.println("classLoader1 = " + classLoader1);
    }
对应的输出结果

systemClassLoader = sun.misc.Launcher$AppClassLoader@18b4aac2
parent = sun.misc.Launcher$ExtClassLoader@61bbe9ba
bootstrapClassLoader = null
classLoader = sun.misc.Launcher$AppClassLoader@18b4aac2
classLoader1 = null

3.Bootstrap ClassLoader

  虚拟机自带的类加载器,启动类加载器

  • 通过C/C++实现的,JVM内置类加载器
  • 作用是用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar、resources.jar或者sun.boot.class.path路径下的内容)、用于提供JVM自身需要的类。
  • 没有继承java.lang.ClassLoader、没有父加载器,自己就是祖先了。
  • 加载扩展类和应用程序类加载器,并指定为他们的父类加载器
  • 出于安全考虑,Bootstrap启动类加载器只加载报名为java,javax,sun等开头的类

4.Extension ClassLoader

虚拟机自带的加载器。扩展类加载器,Java语音编写,是sun.misc.Launcher的内部类

派生于ClassLoader所以是自定义类加载器

父类加载器是BootstrapClassLoader。

扩展类加载器是从扩展目录 java.ext.dirs系统属性指定的目录中加载类库,或者从JDK的安装目录的 jre/lib/ext子目录下加载类库,如果用户创建的jar包也放在了这个目录下,那么该类加载器也会自动加载的。

然后通过案例来看看扩展类加载器加载的路径

    public static void main(String[] args) {
        System.out.println("**************扩展类加载器*************");
        String extDirs = System.getProperty("java.ext.dirs");
        System.out.println("extDirs = " + extDirs);
    }

5. 自定义类加载器

在我们的日常应用程序的开发中,我基本是用不到自定义类加载器的,基本就是由前面介绍的这三个类加载器来相互配合搞定的。但是在有些特殊的情况下我们不希望通过系统的类加载器来处理,这时我们就可以通过自定义类加载来实现了。

  用户自定义类加载器的实现步骤:

  1. 我们可以直接编写 java.lang.ClassLoader 类的实现来完成自定义的处理
  2. 在JDK1.2之前,自定义类加载器时我们总是会继承ClassLoader然后重写loadClass方法,达到自定义类加载的目的,但是在JDK1.2之后建议把自定义的类加载逻辑放在findClass()方法中
  3. 最后在编写自定义类加载的时候,如果没有太过于复杂的需求,可以直接继承URLClassLoader类,这样可以达到简化自定义类加载器的目的

6. 双亲委派机制

   Java虚拟机对class文件采用的是 按需加载的方式,也就是当需要使用该类时才会将他的class文件加载到内存中生成class对象,而且加载某个类的class文件时,Java虚拟机采用的而是双亲委派模式。即把请求交由父类加载器处理,它是一种任务委派模式。

双亲委派的工作原理:

  1. 如果一个类加载器收到了类加载的请求,它并不会自己先去加载,而且把这个请求委托给父类的加载器去执行。
  2. 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归请求,最终将请求流转到顶层的启动类加载器
  3. 如果父类加载器可以完成类加载任务,就成功返回,如果父类无法完成任务,子加载器才会尝试自己去加载。

举个简单的例子,我们自定义一个java.lang.String类,然后添加对应的main方式执行。

public class String {
    public static void main(String[] args) {
        System.out.println("自定义String类");
    }
}

执行结果

原因就是双亲委派机制通过BootstrapClassLoader加载的是java包下的String,而不会加载我们自定义的。

双亲委派机制的有点:

  1. 避免类的重复加载
  2. 保护程序的安全,防止核心API被随意的篡改

Catalina为什么不new出来?

掌握了Java的类加载器和双亲委派机制,现在我们就可以回答正题上来了,Tomcat的类加载器是怎么设计的?

1.Web容器的特性

  Web容器有其自身的特殊性,所以在类加载器这块是不能完全使用JVM的类加载器的双亲委派机制的。在Web容器中我们应该要满足如下的特性:

隔离性

  部署在同一个Web容器上的两个Web应用程序所使用的Java类库可以实现相互隔离。设想一下,两个Web应用,一个使用了Spring3.0,另一个使用了新的的5.0,应用服务器使用一个类加载器,Web应用将会因为jar包覆盖而无法启动。

灵活性:

  Web应用之间的类加载器相互独立,那么就能针对一个Web应用进行重新部署,此时Web应用的类加载器会被重建,而且不会影响其他的Web应用。如果采用一个类加载器,类之间的依赖是杂乱复杂的,无法完全移出某个应用的类。

性能:

  性能也是一个比较重要的点。部署在同一个Web容器上的两个Web应用程序所使用的Java类库可以互相共享。这个需求也很常见,例如,用户可能有10个使用Spring框架的应用程序部署在同一台服务器上,如果把10份Spring分别存放在各个应用程序的隔离目录中,将会是很大的资源浪费——这主要倒不是浪费磁盘空间的问题,而是指类库在使用时都要被加载到Web容器的内存,如果类库不能共享,虚拟机的方法区就会很容易出现过度膨胀的风险。

2.Tomcat类加载器结构

  明白了Web容器的类加载器有多个,再来看tomcat的类加载器结构。

首先上张图,整体看下tomcat的类加载器:

  可以看到在原先的java类加载器基础上,tomcat新增了几个类加载器,包括3个基础类加载器和每个Web应用的类加载器,其中3个基础类加载器可在conf/catalina.properties中配置,具体介绍下:

Common:以应用类加载器为父类,是tomcat顶层的公用类加载器,其路径由conf/catalina.properties中的common.loader指定,默认指向${catalina.base}/lib下的包。

Catalina:以Common类加载器为父类,是用于加载Tomcat应用服务器的类加载器,其路径由server.loader指定,默认为空,此时tomcat使用Common类加载器加载应用服务器。

Shared:以Common类加载器为父类,是所有Web应用的父类加载器,其路径由shared.loader指定,默认为空,此时tomcat使用Common类加载器作为Web应用的父加载器。

Web应用:以Shared类加载器为父类,加载/WEB-INF/classes目录下的未压缩的Class和资源文件以及/WEB-INF/lib目录下的jar包,该类加载器只对当前Web应用可见,对其他Web应用均不可见。

  默认情况下,Common、Catalina、Shared类加载器是同一个,但可以配置3个不同的类加载器,使他们各司其职。

  首先,Common类加载器复杂加载Tomcat应用服务器内部和Web应用均可见的类,如Servlet规范相关包和一些通用工具包。

  其次,Catalina类加载器负责只有Tomcat应用服务器内部可见的类,这些类对Web应用不可见。比如,想实现自己的会话存储方案,而且该方案依赖了一些第三方包,当然是不希望这些包对Web应用可见,这时可以配置server.load,创建独立的Catalina类加载器。

  再次,Shared类复杂加载Web应用共享类,这些类tomcat服务器不会依赖

3. Tomcat的类加载器的继承结构

可以看到继承的结构和我们上面所写的类加载器的结构不同。

大家需要注意双亲委派机制并不是通过继承来实现的,而是相互之间组合而形成的。所以AppClassLoader没有继承自 ExtClassLoader,WebappClassLoader也没有继承自AppClassLoader。至于Common ClassLoader ,Shared ClassLoader,Catalina ClassLoader则是在启动时初始化的三个不同名字的URLClassLoader。


系列文章

  1. 金融级多数据中心灾备互联
  2. IT Governance Framework:IT治理框架
  3. 12306亿级流量架构分析(史上最全)
  4. 基于主数据驱动的数据治理
  5. Netty的内存池机制怎样设计的-CSDN博客
  6. 如何建设金融数据中心-CSDN博客
  7. 英文版企业架构实践-CSDN博客

资料下载和预览地址:

  • 链接: https://pan.baidu.com/s/1LFyFlsIHCv46DBQRfMGP9A 提取码: kx6b 

标签:Web,Tomcat,自定义,ClassLoader,进阶篇,父类,加载
From: https://blog.csdn.net/qq_30621637/article/details/145209405

相关文章

  • day05 tomcat
    tomcat使用点击startup.bat启动成功解决上面启动成功后,输出存在中文乱码找到此文件,超级记事本打开,UTF-8改成GBK 解决某个端口被占用问题找进程idnetstat-ano|findstr8080......
  • windows安装tomcat10.240108
    ​下载安装jdk17:jdk-17_windows-x64_bin.exe配置JAVA环境变量JAVA_HOME:C:\ProgramFiles\Java\jdk-17PATH:%Java_Home%\bin;%Java_Home%\jre\bin;拷贝tomcat10(下载地址:https://tomcat.apache.org/)到目录,设置环境变量CATALINA_HOME:D:\apache-tomcat-10.1.12PATH:%CATALINA......
  • Tomcat自动监听重启.250116
    1.bash脚本vim/home/sh/restart_tomcat.sh#!/bin/sh#configurations:Automaticmonitoringtomcatprocess,hunguptherestartoperation#author:AmadeusLANG="en_US.utf8"exportLANGexportPATH=/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bi......
  • vulfocus靶场实操tomcat-pass-getshell弱口令漏洞
    vulfocus靶场实操之tomcat-pass-getshell弱口令漏洞提前声明:本节所有操作都是在vulfocus靶场中进行操作,严禁在无授权的情况下进行任何的渗透操作。前言:本节主要对vulfocus靶场中tomcat中间件进行模拟攻击,通过该中间件存在的漏洞进入到后台拿到flag,完成该靶场要求。工具:BurpSu......
  • Tauri教程-进阶篇-第二节 命令机制
    “如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》“有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》“维持现状意味着空耗你的努力和生命。”——纪伯伦Tauri技术教程*第五章Tauri的进阶教程第二节命令机制一.......
  • Tauri教程-进阶篇-第一节 自定义启动画面
    “如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》“有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》“维持现状意味着空耗你的努力和生命。”——纪伯伦Tauri技术教程*第五章Tauri的进阶教程第一节自定义启动画面......
  • Tomcat(134) 如何在Tomcat中解决SSL会话缓存问题
    在Tomcat中,SSL会话缓存问题可能会影响SSL握手的效率和整体性能。以下是详细的故障排除和优化步骤,包括代码示例,帮助你解决Tomcat的SSL会话缓存问题。1.启用并配置SSL首先,确保Tomcat已正确配置SSL。以下是基本的SSL配置示例:1.1配置server.xml在server.xml中配置SSL:<Con......
  • Tomcat(133)Tomcat的SSL会话缓存故障排除
    在Tomcat中,SSL会话缓存问题涉及SSL会话的创建、存储和续用。正确配置和管理SSL会话缓存可以提高SSL握手的效率,减少延迟和资源消耗。以下是详细的故障排除和优化步骤,以及相关代码示例。1.确保Tomcat已启用SSL首先,确保Tomcat已正确配置SSL。以下是基本的SSL配置示例:1.1配......
  • MCP(Model Context Protocol)模型上下文协议 进阶篇3 - 传输
    MCP目前定义了两种标准的客户端-服务端通信传输机制:stdio(标准输入输出通信)HTTPwithServer-SentEvents(SSE)(HTTP服务端发送事件)客户端应尽可能支持 stdio。此外,客户端和服务端也可以以插件方式实现自定义传输机制。1.stdio传输在stdio传输中:客户端将MCP服务......
  • tomcat9.0下载安装及配置图文教程
    下载官网:http://tomcat.apache.org/选择下载64-BitWindowszip(Win64)2.解压到任意一个盘,如,D:\apache-tomcat-9.0.983.设置环境变量CATALINA_HOME:D:\apache-tomcat-9.0.98找到系统变量Path,添加:%CATALINA_HOME%\bin验证是否配置成功进入Windows命令行窗口,输入startup.ba......