Tomcat如何检测内存泄漏

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 一般情况下,如果我们重启web应用是通过重启tomcat的话,则不存在内存泄漏问题。但如果不重启tomcat而对web应用进行重加载则可能会导致内存泄漏,因为重加载后有可能会导致原来的某些内存无法让GC回收,例如web应用使用了JDBC,驱动会进行注册,当web应用停止时没有反注册就会导致内存泄漏。
+关注继续查看

一般情况下,如果我们重启web应用是通过重启tomcat的话,则不存在内存泄漏问题。但如果不重启tomcat而对web应用进行重加载则可能会导致内存泄漏,因为重加载后有可能会导致原来的某些内存无法让GC回收,例如web应用使用了JDBC,驱动会进行注册,当web应用停止时没有反注册就会导致内存泄漏。

看看是什么原因导致tomcat内存泄漏的。这个要从热部署开始说起,因为tomcat提供了不必重启容器而只需重启web应用以达到热部署的功能,其实现是通过定义一个WebappClassLoader类加载器,当热部署时就将原来的类加载器废弃并重新实例化一个WebappClassLoader类加载器。但这种方式可能存在内存泄漏问题,因为ClassLoader是一个结构复杂的对象,导致它不能被GC回收的可能性比较多,除了对ClassLoader对象有引用可能导致其无法回收,还可能对其加载的元数据(方法、类、字段等)有引用都会导致无法被GC回收。

内存泄漏

如上图,tomcat的资源由不同类加载器加载,这里只看BootstrapClassLoader和WebappClassLoader两个类加载器,BootstrapClassLoader负责加载rt.jar包的java.sql.DriverManager,WebappClassLoader负责加载web应用中的mysql驱动包,其中有一个很重要的步骤是mysql的驱动类需要注册到DriverManager中,即DriverManager.registerDriver(new Driver()),它由mysql驱动包自动完成。这样一来当web应用进行热部署操作时,没有将mysql的Driver从DriverManager中反注册掉的话,则会导致整个WebappClassLoader回收不了,造成内存泄漏。

接着看tomcat如何对此内存泄漏进行监控的,要判断WebappClassLoader会不会导致内存泄漏只需判断WebappClassLoader有没有被GC回收即可。在Java中有一种引用叫弱引用,它能很好判断WebappClassLoader有没有被GC回收,被弱引用关联的对象只能生存到下一次垃圾回收发生之前,即如果某WebappClassLoader对象只被某弱引用关联,则它会在下次垃圾回收时被回收,但如果WebappClassLoader对象除了被弱引用关联外还被其他对象强引用,那么WebappClassLoader对象是不会被回收的,根据这些条件就可以判断是否有WebappClassLoader内存泄漏了。

Tomcat的实现是通过WeakHashMap来实现弱引用的,只需将WebappClassLoader对象put到WeakHashMap中,例如weakMap.put(“a”,webappClassLoader),当webappClassLoader及其包含的元素没有被其它任何类加载器中的元素引用到时,JVM发生垃圾回收时则会把webappClassLoader对象回收。

简单的实现代码大致如下:

public class MemoryLeakTest{
private Map<ClassLoader, String> childClassLoaders = new WeakHashMap<ClassLoader, String>();
public String[] findReloadedContextMemoryLeaks() {
        System.gc();
        List<String> result = new ArrayList<String>();
        for (Map.Entry<ClassLoader, String> entry : childClassLoaders.entrySet()) {
            ClassLoader cl = entry.getKey();
            if (!((WebappClassLoader) cl).isStarted()) {
                result.add(entry.getValue());
            }
        }
        return result.toArray(new String[result.size()]);
    }
}

使用一个WeakHashMap用于跟踪WebappClassLoader,在查找内存泄漏之前会先强制调用System.gc();进行一次垃圾回收,保证没问题的WebappClassLoader都被回收掉,这时如果还有WebappClassLoader的状态是非started(正常启动的都为started,关闭了的则为非started)的,则是未被垃圾回收的WebappClassLoader,属于内存泄漏的。

点击订购作者《Tomcat内核设计剖析》

博主的书

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
28天前
|
jenkins 应用服务中间件 持续交付
gitlab、jenkins、tomcat内存限制
gitlab、jenkins、tomcat内存限制
22 0
|
7月前
|
数据挖掘 应用服务中间件 容器
手把手教你实现tomcat内存马
手把手教你实现tomcat内存马
|
10月前
|
Oracle Java 关系型数据库
内存溢出之Tomcat内存配置-catalina.sh or catalina.bat
内存溢出之Tomcat内存配置-catalina.sh or catalina.bat
389 0
内存溢出之Tomcat内存配置-catalina.sh or catalina.bat
|
10月前
|
安全 Java 应用服务中间件
从一个被Tomcat拒绝的漏洞到特殊内存马
从一个被Tomcat拒绝的漏洞到特殊内存马
121 0
从一个被Tomcat拒绝的漏洞到特殊内存马
|
域名解析 缓存 安全
Tomcat - 如何优化 Tomcat 配置(内存、并发、缓存)优化
Tomcat - 如何优化 Tomcat 配置(内存、并发、缓存)优化
359 0
|
监控 Java 应用服务中间件
通过JConsoler监控Tomcat的JVM内存
通过JConsoler监控Tomcat的JVM内存 文章目录 通过JConsoler监控Tomcat的JVM内存 1.监控Tomcat的方式 2.Java自带的监控命令 3.Tomcat故障案例 10.4.配置Tomcat JMX监控 5.使用Jsconsole连接JMX查看监控数据
179 0
通过JConsoler监控Tomcat的JVM内存
|
监控 Java 应用服务中间件
zabbix监控tomcat的jvm内存(二十七)
zabbix监控tomcat的jvm内存 1.介绍 tomcat监控主要是jvm,又来了jvm监控我们可以看到jvm的内存使用情况,内存溢出情况 zabbix监控tomcat使用的是zabbix-java-gateway,zabbix-java-gateway需要java环境
430 0
zabbix监控tomcat的jvm内存(二十七)
|
监控 Java 应用服务中间件
Linux:PS查看进程信息,和查看tomcat内存等信息
Linux:PS查看进程信息,和查看tomcat内存等信息
377 0
|
缓存 网络协议 Java
Tomcat调优总结【内存和线程】
Tomcat调优总结【内存和线程】
214 0
Tomcat调优总结【内存和线程】
|
Java 应用服务中间件 Linux
Tomcat内存释放不了、Tomcat内存溢出原因
公司的tomcat又挂掉了,之前挂了一次.出现以下错误,后来把tomcat的内存增大到1024 严重: Exception initializing page context java.lang.OutOfMemoryError: Java heap space 在tomcat\bin\catalina.bat的set CURRENT_DIR=%cd% 前面添加 set JAVA_OPTS =-Xms512m -Xmx1024m 意思:设置最小虚拟内存512,最大1024.
378 0
热门文章
最新文章
相关产品
云迁移中心
推荐文章
更多