您当前的位置:首页 > 电脑百科 > 站长技术 > 服务器

Tomcat深入解析与性能优化

时间:2020-11-11 10:59:24  来源:  作者:
Tomcat深入解析与性能优化

 

前言

 

JAVA 应用中,常用的 Web 服务器一般由 Tomcat、weblogic、jetty、undertwo等。但从 Java 2019和2020 生态使用报告可以看到,tomcat的用户量对比明显较大,当然这也基于它开源和免费的特点。

 

Java 2019 年生态圈使用报告

Tomcat深入解析与性能优化

 

2020 Java 生态系统报告

Tomcat深入解析与性能优化

 

从软件架构的发展角度来看,软件架构大致经历了如下几个阶段:

Tomcat深入解析与性能优化

 

从 Java Web 角度来说,架构大致经历了:

Tomcat深入解析与性能优化

 

从当前企业使用的架构角度来说,使用SSM架构项目比较多,SSH基本被淘汰(大部分是老项目维护),很大一部分企业转向微服务架构了。

 

基于Spring 生态来说,大部分中小型企业都基本使用SpringBoot,SpringBoot本身集成了 tomcat、jetty和undertwo 容器,那么我们为什么需要花时间来研究tomcat呢?

  1. 当前tomcat依然是主流java web容器,研究它符合java 技术生态发展;
  2. 在java web项目调优中,如ssm项目中,在优化项目时,jvm和tomcat同样重要,都需要优化;
  3. 尽管springboot内置了tomcat容器,且配置了默认的tomcat参数,但当默认的tomcat参数满足不了项目优化要求时,就需要优化人员手动进行相关的参数优化,因此研究tomcat非常必要;
  4. 熟悉tomcat架构,是后续进行项目优化的基础,也是必备条件。

Tomcat架构说明


知识点:

 

  1. Tomcat目录结构
  2. Tomcat简要架构
  3. Tomcat各组件及关系
  4. Tomcat server.xml配置详解
  5. Tomcat启动参数说明(启动脚本)

 

Tomcat 是一个基于JAVA的WEB容器,其实现了JAVA EE中的 Servlet 与 jsp 规范,与Nginx Apache 服务器不同在于一般用于动态请求处理。在架构设计上采用面向组件的方式设计。即整体功能是通过组件的方式拼装完成。另外每个组件都可以被替换以保证灵活性。

Tomcat深入解析与性能优化

 

通过Tomcat官方可以看到,目前已经更新到Tomcat 10了,但当前大部分企业使用的Tomcat 为8或者9版本。

Tomcat深入解析与性能优化

 

Tomcat 目录结构

Tomcat深入解析与性能优化

 

  • bin:可执行文件,.sh结尾的表示linux可执行文件,.bat结尾的表示windows可执行文件
  • conf:配置文件
  • lib:tomcat相关jar包
  • temp:临时文件
  • webApps:存放项目
  • work:工作目录

bin目录

 

bin目录存放可执行文件,简要结束常用命令

Tomcat深入解析与性能优化

 

这里主要解释如下通用的命令,其他命令就不一一介绍

  • catalina.sh 真正启动Tomcat文件,可以在里面设置jvm参数
  • startup.sh 程序项目命令文件
  • version.sh 查看tomcat版本相关信息命令文件
  • shutdown.sh 关闭程序命令

 

conf目录

 

conf文件夹用来存放tomcat相关配置文件

Tomcat深入解析与性能优化

 

1.catalina.policy

 

项目安全文件,用来防止欺骗代码或JSP执行带有像System.exit(0)这样的命令的可能影响容器的破坏性代码. 只有当Tomcat用-security命令行参数启动时这个文件才会被使用,即启动tomcat时, startup.sh -security 。

Tomcat深入解析与性能优化

 

上图中,tomcat容器下部署两个项目,项目1和项目2。由于项目1中有代码System.exit(0),当访问该代码时,该代码会导致整个tomcat停止,从而也导致项目2停止。

 

为了解决因项目1存在欺骗代码或不安全代码导致损害Tomcat容器,从而影响其他项目正常运行的问题,启动tomcat容器时,加上-security参数就,即startup.sh -security,如此即使项目1中有代码System.exit(0),也只会仅仅停止项目1,而不会影响Tomcat容器,然而起作用的配置文件就是catalina.policy文件。

 

2.catalina.properties

 

配置tomcat启动相关信息文件

 

3.context.xml

 

监视并加载资源文件,当监视的文件发生发生变化时,自动加载

Tomcat深入解析与性能优化

 

 

4.jaspic-providers.xml 和 jaspic-providers.xsd

 

这两个文件不常用

 

5.logging.properties

 

该文件为tomcat日志文件,包括配置tomcat输出格式,日志级别等

 

6.server.xml

 

tomcat核心架构主件文件,下面会详细解析。

 

7.tomcat-users.xml和tomcat-users.xsd

 

tomcat用户文件,如配置远程登陆账号

 

tomcat-users.xsd 为tomcat-users.xml描述和约束文件

 

8.web.xml

 

tomcat全局配置文件。

 

lib目录

 

lib文件夹主要用来存放tomcat依赖jar包,如下为 tomcat 的lib文件夹下的相关jar包。

Tomcat深入解析与性能优化

 

每个jar包功能,这里就不讲解了,这里主要分析ecj-4.13.jar,这个jar包起到将.java编译成.class字节码作用。

 

假设要编译MyTest.java,那么jdk会执行两步:

  • 第一步:将MyTest.java编译成MyTest.class

javac MyTest.java

  • 第二步:执行MyTest.class

java MyTest.class

  • 那么,使用ecj-4.13.jar如执行MyTest.java呢?

java -jar ecj-4.13.jar MyTest.java

 

logs目录

 

该文件夹表示tomcat日志文件,大致包括如下六类文件:

Tomcat深入解析与性能优化

 


Tomcat深入解析与性能优化

 

temp目录

 

temp目录用户存放tomcat在运行过程中产生的临时文件。(清空不会对tomcat运行带来影响)。

 

webapps目录

 

webapps目录用来存放应用程序,当tomcat启动时会去加载webapps目录下的应用程序。可以以文件夹、war包、jar包的形式发布应用。

当然,你也可以把应用程序放置在磁盘的任意位置,在配置文件中映射好就行。

 

work目录

 

work目录用来存放tomcat在运行时的编译后文件,例如JSP编译后的文件。

清空work目录,然后重启tomcat,可以达到清除缓存的作用。

 

Tomcat 简要架构

 

Tomcat深入解析与性能优化

 

Tomcat 各组件及关系

  • Server 和 Service
  • Connector 连接器
    • HTTP 1.1
    • SSL https
    • AJP( Apache JServ Protocol) apache 私有协议,用于apache 反向代理Tomcat
  • Container
    • Engine 引擎 catalina
    • Host 虚拟机 基于域名 分发请求
    • Context 隔离各个WEB应用 每个Context的 ClassLoader都是独立
  • Component
    • Manager (管理器)
    • logger (日志管理)
    • loader (载入器)
    • pipeline (管道)
    • valve (管道中的阀)

 

Tomcat深入解析与性能优化

 

Tomcat server.xml 配置详解


Server 的基本基本配置:

<Server>
    <Listener /><!-- 监听器 -->
    <GlobaNamingResources> <!-- 全局资源 -->
    </GlobaNamingResources
    <Service>          <!-- 服务 用于 绑定 连接器与 Engine -->
        <Connector 8080/> <!-- 连接器-->
        <Connector 8010 /> <!-- 连接器-->
        <Connector 8030/> <!-- 连接器-->
        
        <Engine>      <!-- 执行引擎-->
            <Logger />
            <Realm />
               <host "www.test.com" appBase="">  <!-- 虚拟主机-->
                   <Logger /> <!-- 日志配置-->
                   <Context "/applction" path=""/> <!-- 上下文配置-->
               </host>
        </Engine>
    </Service>
</Server>

 

server

root元素:server 的顶级配置

主要属性:

port:执行关闭命令的端口号

shutdown:关闭命令

 

  • 演示shutdown的用法
#基于telent 执行SHUTDOWN 命令即可关闭
telent 127.0.0.1 8005
SHUTDOWN

 

service

 

服务:将多个connector 与一个Engine组合成一个服务,可以配置多个服务。

 

Connector

 

连接器:用于接收 指定协议下的连接 并指定给唯一的Engine 进行处理。

 

主要属性:

  • protocol 监听的协议,默认是http/1.1
  • port 指定服务器端要创建的端口号
  • minThread 服务器启动时创建的处理请求的线程数
  • maxThread 最大可以创建的处理请求的线程数
  • enableLookups 如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址
  • redirectPort 指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号
  • acceptCount 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认100;
  • address 绑定客户端特定地址,127.0.0.1
  • bufferSize 每个请求的缓冲区大小 bufferSize * maxThreads
  • compression 是否启用文档压缩
  • compressionMinSize 文档压缩的最小大小
  • compressableMimeTypes text/html,text/xml,text/plain
  • connectionTimeout 客户端发起链接到服务端接收为止,指定超时的时间数(以毫秒为单位)
  • connectionUploadTimeout upload情况下连接超时时间
  • disableUploadTimeout 如果为true则使用 connectionTimeout
  • keepAliveTimeout 当长链接闲置 指定时间主动关闭 链接 ,前提是客户端请求头 带上这个 head"connection" " keep-alive"
  • maxKeepAliveRequests 最大的 长连接数 默认最大100
  • maxSpareThreads BIO 模式下 最多线闲置线程数
  • minSpareThreads BIO 模式下 最小线闲置线程数
  • SSLEnabled 是否开启 sll 验证,在Https 访问时需要开启。

 

  • 演示配置多个Connector
 <Connector port="8860" protocol="org.apache.coyote.http11.Http11NioProtocol"
                connectionTimeout="20000"
                redirectPort="8862"
                URIEncoding="UTF-8"
                useBodyEncodingForURI="true"
                compression="on" compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/JavaScript,text/css,application/x-json,application/json,application/x-javascript"
                maxThreads="1024" minSpareThreads="200"
                acceptCount="800"
                enableLookups="false"
        />

 

Engine

 

引擎:用于处理连接的执行器,默认的引擎是catalina。一个service 中只能配置一个Engine。

主要属性:name 引擎名称 defaultHost 默认host

 

Host

虚拟机:基于域名匹配至指定虚拟机。类似于nginx 当中的server,默认的虚拟机是localhost.

  • 演示配置多个Host
<Host name="www.test.com"  appBase="/usr/www/test"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"               prefix="www.luban.com.access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
</Host>

 

Context

 

应用上下文:一个host 下可以配置多个Context ,每个Context 都有其独立的classPath。相互隔离,以免造成ClassPath 冲突。

 

  • 演示配置多个Context
<Context docBase="hello" path="/h" reloadable="true"/>

 

Valve

 

阀门:可以理解成request 的过滤器,具体配置要基于具体的Valve 接口的子类。以下即为一个访问日志的Valve.

 

 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="www.luban.com.access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

 

Tomcat启动参数说明

 

我们平时启动Tomcat过程是怎么样的?

  1. 复制WAR包至Tomcat webapp 目录。
  2. 执行starut.bat 脚本启动。
  3. 启动过程中war 包会被自动解压装载。

但是我们在Eclipse 或idea 中启动WEB项目的时候 也是把War包复杂至webapps 目录解压吗?显然不是,其真正做法是在Tomcat程序文件之外创建了一个部署目录,在一般生产环境中也是这么做的 即:Tomcat 程序目录和部署目录分开 。

我们只需要在启动时指定CATALINA_HOME 与 CATALINA_BASE 参数即可实现。

Tomcat深入解析与性能优化

 

可以编写一个脚本 来实现自定义配置:

更新 启动 脚本

#!/bin/bash -e
export now_time=$(date +%Y-%m-%d_%H-%M-%S)
echo "deploy time:$now_time"

app=$1
version=$2
mkdir -p war/
#从svn下载程序至 war目录
war=war/${app}_${version}.war
echo "$war"
svn export svn://192.168.0.253/release/${app}_${version}.war $war

deploy_war() {
#解压版本至当前目录
target_dir=war/${app}_${version}_${now_time}
unzip -q $war -d $target_dir
rm -f appwar
ln -sf $target_dir appwar
target_ln=`pwd`/appwar
echo '<?xml version="1.0" encoding="UTF-8" ?>
<Context docBase="'$target_ln'" allowLinking="false">
</Context>' > conf/Catalina/localhost/ROOT.xml
#重启Tomcat服务
./tomcat.sh restart
}

deploy_war
```

 

自动部署脚本

#!/bin/bash -e
export now_time=$(date +%Y-%m-%d_%H-%M-%S)
echo "deploy time:$now_time"

app=$1
version=$2
mkdir -p war/
#从svn下载程序至 war目录
war=war/${app}_${version}.war
echo "$war"
svn export svn://192.168.0.253/release/${app}_${version}.war $war

deploy_war() {
#解压版本至当前目录
target_dir=war/${app}_${version}_${now_time}
unzip -q $war -d $target_dir
rm -f appwar
ln -sf $target_dir appwar
target_ln=`pwd`/appwar
echo '<?xml version="1.0" encoding="UTF-8" ?>
<Context docBase="'$target_ln'" allowLinking="false">
</Context>' > conf/Catalina/localhost/ROOT.xml
#重启Tomcat服务
./tomcat.sh restart
}

deploy_war
```

 

Tomcat 网络通信模型剖析


Tomcat 支持四种线程模型介绍

 

什么是IO?

IO是指为数据传输所提供的输入输出流,其输入输出对象可以是:文件、网络服务、内存等。

Tomcat深入解析与性能优化

 

什么是IO模型?

 

提问:

假设应用在从硬盘中读取一个大文件过程中,此时CPU会与硬盘一样处于高负荷状态么?

 

演示:

  • 演示观察大文件的读写过程当中CPU 有没有发生大波动。

 

演示结果:CPU 没有太高的增长

 

通常情况下IO操作是比较耗时的,所以为了高效的使用硬件,应用程序可以用一个专门线程进行IO操作,而另外一个线程则利用CPU的空闲去做其它计算。这种为提高应用执行效率而采用的IO操作方法即为IO模型。

 

各IO模型简要说明

BIO

阻塞式IO,即Tomcat使用传统的java.io进行操作。该模式下每个请求都会创建一个线程,对性能开销大,不适合高并发场景。优点是稳定,适合连接数目小且固定架构。

NIO

非阻塞式IO,jdk1.4 之后实现的新IO。该模式基于多路复用选择器监测连接状态在通知线程处理,从而达到非阻塞的目的。比传统BIO能更好的支持并发性能。Tomcat 8.0之后默认采用该模式

APR

全称是 Apache Portable Runtime/Apache可移植运行库),是Apache HTTP服务器的支持库。可以简单地理解为,Tomcat将以JNI的形式调用Apache HTTP服务器的核心动态链接库来处理文件读取或网络传输操作。使用需要编译安装APR 库

AIO

异步非阻塞式IO,jdk1.7后之支持 。与nio不同在于不需要多路复用选择器,而是请求处理线程执行完成进行回调调制,已继续执行后续操作。Tomcat 8之后支持。

Tomcat深入解析与性能优化

 

使用指定IO模型的配置方式:

 

配置 server.xml 文件当中的 <Connector protocol="HTTP/1.1"> 修改即可。

默认配置 8.0 protocol=“HTTP/1.1” 8.0 之前是 BIO, 8.0 之后是 NIO

 

  • BIO

protocol=“org.apache.coyote.http11.Http11Protocol”

  • NIO

protocol=“org.apache.coyote.http11.Http11NioProtocol”

  • AIO

protocol=“org.apache.coyote.http11.Http11Nio2Protocol”

  • APR

protocol=“org.apache.coyote.http11.Http11AprProtocol”

 

Tomcat BIO、NIO实现过程源码解析

 

BIO 与NIO区别

分别演示在高并发场景下BIO与NIO的线程数的变化?

Tomcat深入解析与性能优化

 

BIO 配置

<Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol"
               connectionTimeout="20000"
               redirectPort="8443"
               compression="on" compressionMinSize="1024"
               compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript"
               maxThreads="500" minSpareThreads="1"/>

 

NIO配置

 <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="8443"
               compression="on" compressionMinSize="1024"
               compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript"
               maxThreads="500" minSpareThreads="1"/>

 

演示数据:

Tomcat深入解析与性能优化

 

生成环境重要因素:

  1. 网络
  2. 程序执行业务用时

 

源代码地址:https://github.com/org-hejianhui/bit-bigdata-transmission

 

BIO 线程模型

Tomcat深入解析与性能优化

 

BIO 源码

 

线程组:

Accept 线程组 acceptorThreadCount 默认1个

exec 线程组 maxThread

JIoEndpoint

Acceptor extends Runnable

SocketProcessor extends Runnable

Tomcat深入解析与性能优化

 

NIO 线程模型

Tomcat深入解析与性能优化

 

NIO 线程模型

 

Accept 线程组 默认两个轮询器

Poller Selector PollerEvent轮询线程状态

SocketProcessor

Tomcat深入解析与性能优化

 

 

BIO

线程数量 会受到 客户端阻塞、网络延迟、业务处理慢===>线程数会更多。

 

NIO

线程数量 会受到业务处理慢===>线程数会更多。

 

Tomcat connector 并发参数解读

 

Tomcat深入解析与性能优化

 

Tomcat 类加载机制源码解析

 

类加载的本质

 

是用来加载 Class 的。它负责将 Class 的字节码形式转换成内存形式的 Class 对象。字节码可以来自于磁盘文件 .class,也可以是 jar 包里的 .class,也可以来自远程服务器提供的字节流,字节码的本质就是一个字节数组 []byte,它有特定的复杂的内部格式。

 

JVM 运行实例中会存在多个 ClassLoader,不同的 ClassLoader 会从不同的地方加载字节码文件。它可以从不同的文件目录加载,也可以从不同的 jar 文件中加载,也可以从网络上不同的静态文件服务器来下载字节码再加载。

 

jvm里ClassLoader的层次结构

Tomcat深入解析与性能优化

 

类加载器层次结构

 

BootstrapClassLoader(启动类加载器)

 

称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等,可通过如下程序获得该类加载器从哪些地方加载了相关的jar或class文件:

URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (URL url : urLs) {
    System.out.println(url.toExternalForm());
}

程序执行结果如下:

file:/Library/Java/JavaVirtualmachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/sunrsasign.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/classes

从rt.jar中选择String类,看一下String类的类加载器是什么

ClassLoader classLoader = String.class.getClassLoader();
System.out.println(classLoader);

执行结果如下:

null

 

可知由于BootstrapClassLoader对Java不可见,所以返回了null,我们也可以通过某一个类的加载器是否为null来作为判断该类是不是使用BootstrapClassLoader进行加载的依据。

 

ExtensionClassLoader

 

ExtClassLoader称为扩展类加载器,主要负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目录下的所有jar包或者由java.ext.dirs系统属性指定的jar包.放入这个目录下的jar包对AppClassLoader加载器都是可见的(因为ExtClassLoader是AppClassLoader的父加载器,并且Java类加载器采用了委托机制)。

 

ExtClassLoader的类扫描路径通过执行下面代码来看一下:

String extDirs = System.getProperty("java.ext.dirs");
for (String path : extDirs.split(";")) {
System.out.println(path);
}

执行结果如下(Mac系统):

/Users/hjh/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

jre/lib/ext路径下内容为:

Tomcat深入解析与性能优化

 

从上面的路径中随意选择一个类,来看看它的类加载器是什么:

sun.misc.Launcher$ExtClassLoader@4439f31e
null

从上面的程序运行结果可知ExtClassLoader的父加载器为null,之前说过BootstrapClassLoader对Java不可见,所以返回了null。ExtClassLoader的父加载器返回的是null,那是否说明ExtClassLoader的父加载器是BootstrapClassLoader?

 

Bootstrap ClassLoader是由C/C++编写的,它本身是虚拟机的一部分,所以它并不是一个JAVA类,也就是无法在java代码中获取它的引用,JVM启动时通过Bootstrap类加载器加载rt.jar等核心jar包中的class文件,之前的int.class,String.class都是由它加载。然后呢,我们前面已经分析了,JVM初始化sun.misc.Launcher并创建Extension ClassLoader和AppClassLoader实例。并将ExtClassLoader设置为AppClassLoader的父加载器。Bootstrap没有父加载器,但是它却可以作用一个ClassLoader的父加载器。比如ExtClassLoader。这也可以解释之前通过ExtClassLoader的getParent方法获取为Null的现象

 

AppClassLoader

才是直接面向我们用户的加载器,它会加载 Classpath 环境变量里定义的路径中的 jar 包和目录。我们自己编写的代码以及使用的第三方 jar 包通常都是由它来加载的。

 

加载System.getProperty("java.class.path")所指定的路径或jar。在使用Java运行程序时,也可以加上-cp来覆盖原有的Classpath设置,例如: java -cp ./lavasoft/classes HelloWorld

 

public class AppClassLoaderTest {
    public static void main(String[] args) {
        System.out.println(ClassLoader.getSystemClassLoader());
    }
}

 

输出结果如下:

sun.misc.Launcher$AppClassLoader@18b4aac2

 

以上结论说明调用ClassLoader.getSystemClassLoader()可以获得AppClassLoader类加载器。

protected ClassLoader() {
    this(checkCreateClassLoader(), getSystemClassLoader());
}

通过查看ClassLoader的源码发现并且在没有特定说明的情况下,用户自定义的任何类加载器都将该类加载器作为自定义类加载器的父加载器。

 

通过执行上面的代码即可获得classpath的加载路径。

 

在上面的main函数的类的加载就是使用AppClassLoader加载器进行加载的,可以通过执行下面的代码得出这个结论

public class AppClassLoaderTest {

    public static void main(String[] args) {
        ClassLoader classLoader = Test.class.getClassLoader();
        System.out.println(classLoader);
        System.out.println(classLoader.getParent());
    }

    private static class Test {

    }

}

 

执行结果如下:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@2d209079

从上面的运行结果可以得知AppClassLoader的父加载器是ExtClassLoader

 

Tomcat的 类加载顺序

 

Tomcat深入解析与性能优化

 

在Tomcat中,默认的行为是先尝试在Bootstrap和Extension中进行类型加载,如果加载不到则在Webapp ClassLoader中进行加载,如果还是找不到则在Common中进行查找。

 

NoClassDefFoundError

 

NoClassDefFoundError是在开发JavaEE程序中常见的一种问题。该问题会随着你所使用的JavaEE中间件环境的复杂度以及应用本身的体量变得更加复杂,尤其是现在的JavaEE服务器具有大量的类加载器。

在JavaDoc中对NoClassDefFoundError的产生是由于JVM或者类加载器实例尝试加载类型的定义,但是该定义却没有找到,影响了执行路径。换句话说,在编译时这个类是能够被找到的,但是在执行时却没有找到。

这一刻IDE是没有出错提醒的,但是在运行时却出现了错误。

 

NoSuchMethodError

 

在另一个场景中,我们可能遇到了另一个错误,也就是NoSuchMethodError。

NoSuchMethodError代表这个类型确实存在,但是一个不正确的版本被加载了。

 

ClassCastException

 

ClassCastException,在一个类加载器的情况下,一般出现这种错误都会是在转型操作时,比如:A a = (A) method();,很容易判断出来method()方法返回的类型不是类型A,但是在 JavaEE 多个类加载器的环境下就会出现一些难以定位的情况。

 

部分图片来源于网络,版权归原作者,侵删。


Tags:Tomcat   点击:()  评论:()
声明:本站部分内容来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除,谢谢。
▌相关评论
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
▌相关推荐
前言 在 Java 应用中,常用的 Web 服务器一般由 tomcat、weblogic、jetty、undertwo等。但从 Java 2019和2020 生态使用报告可以看到,tomcat的用户量对比明显较大,当然这也基于...【详细内容】
2020-11-11   Tomcat  点击:(3)  评论:(0)  加入收藏
一,前言我们都知道,tomcat启动前需要配置JDK环境变量,如果没有配置JDK的环境变量,那么tomcat启动的时候就会报错,也就是无法启动。但是在我们的工作或者学习过程中,有的时候会出现...【详细内容】
2020-10-09   Tomcat  点击:(5)  评论:(0)  加入收藏
netty 简介Netty一个基于NIO的客户、服务器端的编程框架1.环境准备maven依赖 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</a...【详细内容】
2020-09-27   Tomcat  点击:(12)  评论:(0)  加入收藏
背景基于Springboot应用以war包的形式运行在tomcat容器中,当更新war包时会有一段时间服务返回404,这对于线上服务是不可接受的。4层的负载均衡可以自动将80端口关闭的节点下线...【详细内容】
2020-09-25   Tomcat  点击:(4)  评论:(0)  加入收藏
一、下载安装jdk并配置1.1 进行JDK下载 下载地址:一键直达JDK下载展示图 一般下载后,安装位置默认,一路下一步,一直到安装完毕-“关闭”。1.2 环境变量配置不要管是不是一般情况...【详细内容】
2020-09-03   Tomcat  点击:(5)  评论:(0)  加入收藏
要明白HTTP长连接,得先明白Socket连接什么是Socket?百度一下,根本看不懂要理解Socket,得先理解TCP TCP是传输层协议,有Linux、Windows等操作系统实现Socket是对TCP协议抽象出来的...【详细内容】
2020-08-20   Tomcat  点击:(11)  评论:(0)  加入收藏
1.1 Tomcat简介Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。Tomcat服务器是一个...【详细内容】
2020-08-10   Tomcat  点击:(5)  评论:(0)  加入收藏
1. 浏览器访问服务器的流程浏览器访问服务器使用的是 Http协议 , Http协议 是应用层协议,用于定义数据通信的格式,具体的数据传输使用的是 TCP/IP协议 。 2. Tomcat 系统总体架...【详细内容】
2020-08-04   Tomcat  点击:(2)  评论:(0)  加入收藏
#!/bin/bash# func:tomcat 6.0/7.0/8.5/9.0 安装# 定义安装目录、及日志信息. /etc/init.d/functions[ $(id -u) != "0" ] && echo "请使用root用户执行" && exit 1export P...【详细内容】
2020-08-02   Tomcat  点击:(14)  评论:(0)  加入收藏
今天我们来聊一聊用Nginx和httpd对tomcat集群做负载均衡的配置以及需要注意的点;在前边的演示和配置都是以单台tomcat来配置使用;但是在生产中单台tomcat实在支撑不了大规模的访问,这个时候我们就需要考虑把多台tomcat做...【详细内容】
2020-07-20   Tomcat  点击:(46)  评论:(0)  加入收藏
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,因为Tom...【详细内容】
2020-07-20   Tomcat  点击:(5)  评论:(0)  加入收藏
Tomcat 架构原理解析到架构设计借鉴Tomcat 发展这么多年,已经比较成熟稳定。在如今『追新求快』的时代,Tomcat 作为 Java Web 开发必备的工具似乎变成了『熟悉的陌生人』,难道...【详细内容】
2020-07-15   Tomcat  点击:(6)  评论:(0)  加入收藏
01 事件背景6月25日, Apache 官方安全团队通过邮件公开报告了一个高危漏洞,邮件中介绍了 HTTP/2 拒绝服务漏洞的细节及解决方案。如下图所示:漏洞详情链接:http://mail-archives...【详细内容】
2020-07-09   Tomcat  点击:(14)  评论:(0)  加入收藏
Promethues 监控tomcat 主要用的模块 Promethus 负载抓取/存储指标信息、并提供查询功能 grafana 数据可视化 JMX exporter 提供JMX中JVM相关的metrics1、利用JMX exporter,...【详细内容】
2020-07-05   Tomcat  点击:(1)  评论:(0)  加入收藏
首先我们通过一张简化的类图来回顾一下,从图上你可以看到各种组件的层次关系,图中的虚线表示一个请求在 Tomcat 中流转的过程。 上面这张图描述了组件之间的静态关系,如果想让...【详细内容】
2020-06-12   Tomcat  点击:(7)  评论:(0)  加入收藏
上一次分享了中间件-部署tomcat文章,那么实际一些最基础的tomcat知识有没有去了解呢?这里简单介绍下一些知识点,希望大家喜欢。 知识点1:tomcat的日志文件解压tomcat之后,会有个l...【详细内容】
2020-06-09   Tomcat  点击:(23)  评论:(0)  加入收藏
前言上一次分享了中间件-部署tomcat文章,那么实际一些最基础的tomcat知识有没有去了解呢?这里简单介绍下一些知识点,希望大家喜欢。 知识点1:tomcat的日志文件解压tomcat之后,会...【详细内容】
2020-06-09   Tomcat  点击:(6)  评论:(0)  加入收藏
1 检查是否禁止Tomcat列表显示文件将web.xml文件中listings配置false2 检查是否禁止超级用户启用tomcat使用普通用户启动tomcat3检查是否配置Tomcat错误页面重定向1. web.xm...【详细内容】
2020-06-09   Tomcat  点击:(47)  评论:(0)  加入收藏
一、安装tomcat点击链接进入官网下载 https://tomcat.apache.org/进去点击左边Download选择版本(建议选择8或9版本),点击右边箭头下载64位版本 下载完解压二、配置环境变量右...【详细内容】
2020-06-05   Tomcat  点击:(36)  评论:(0)  加入收藏
作为免费开源的轻量级Web应用服务器,Tomcat在中小型系统或并发访问用户不是很多的情况下被广泛使用,是开发和调试JSP程序的不错之选,Tomcat也因性能稳定且免费,深受Java爱好者的...【详细内容】
2020-06-04   Tomcat  点击:(2)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条