tomcat配置问题导致的OOM、频繁FullGC问题排查

本文详细解析了在生产环境中遇到的Tomcat服务频繁Full GC问题,通过Prometheus监控发现老年代内存异常,进一步分析发现是由于max-http-header-size配置不合理导致的大量byte[]数组占用内存。文章分享了如何定位问题根源,包括查看GC根持有引用,以及通过修改配置解决内存占用过高的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生产某台服务出现频繁fullgc,一看Prometheus监控,老年代内存一看就很有问题,突然陡峭的曲线,就像房价一样。
在这里插入图片描述
导出dump文件到本地查看,有个byte对象都是10M大小,占了内存的80%以上,简单一看是http请求的信息,事情似乎有点眉目。
在这里插入图片描述
再看GC根谁持有了byte[]数组的引用。
在这里插入图片描述
这符合之前的猜测,是tomcat的线程在处理过程中分配了10M的buffer在堆上。至此,马上可以想到一定是什么参数设置的不合理导致了这种情况,一般而言tomcat不可能为每一个请求分配如此大的buffer。

检查代码里是否有tomcat或服务器相关配置,看到有这么一个配置:
max-http-header-size: 10000000
至此,基本已经确定就是这个不合理的最大http请求头参数导致的问题。

可以打开线程视图,搜索一下tomcat的工作线程,发现线程数量的确很多有401个,但是也只是800的一半。
在这里插入图片描述
另外,发现除了有10008192字节的数组还有10000000字节的数组,查看引用路径可以看到这个正好是10M的数组是output buffer,区别于之前看到的input buffer
在这里插入图片描述
本地验证:
本地启动用visualVM监控,jmeter压测了一波,重现了这个陡峭的曲线。
在这里插入图片描述

修改配置max-http-header-size:4096后,曲线变得正常。
在这里插入图片描述

<think>好的,用户想排查Java服务高内存占用的问题。首先,我需要回忆一下之前学过的关于内存泄漏和性能优化的知识。记得之前看过几个引用,比如引用[1]提到如何诊断内存泄漏,引用[2]讲的是用top或htop监控进程,引用[3]则提到OOM错误的分析可能不准确,需要使用Arthas工具。 首先,用户的问题是如何诊断和解决Java服务的高内存使用。我应该从基础步骤开始,比如监控工具的使用,然后逐步深入分析。可能涉及的步骤包括使用top或htop查看进程内存情况,然后用jstat检查GC情况,接着用jmap生成堆转储,再用MAT或VisualVM分析堆转储,找出内存泄漏的对象。另外,引用[3]中提到Arthas工具,可以用来动态诊断,比如监控方法调用、查看堆内存中的对象统计,这也是一个重要的点。 接下来,解决方案需要分步骤,用户可能需要具体的操作命令,比如如何运行jmap,如何启动jvisualvm,或者如何使用Arthas的dashboard命令。同时,要提醒用户注意OOM错误的分析不能只看表面信息,需要结合多个工具的结果。 还要考虑到优化建议,比如调整JVM参数,优化代码中的数据结构,避免内存泄漏的常见原因如未关闭的资源、静态集合类等。这部分可以引用[1]中的步骤,强调细致分析的重要性。 最后,生成相关问题的时候,需要围绕用户的问题展开,比如如何预防内存泄漏,JVM参数配置,或者Arthas的其他功能。确保问题相关且有逻辑联系。 现在需要把所有这些整理成一个结构清晰的回答,分步骤说明,每个步骤包含具体方法和工具的使用,并正确引用提到的资料。同时,语言要简洁明了,符合用户要求的系统级指令,比如使用中文,正确使用LaTeX格式,生成相关问题等。</think>### Java服务高内存占用的诊断与解决方法 #### 一、初步监控与分析 1. **使用系统工具定位进程** - 通过`top`或`htop`查看内存占用最高的进程: ```bash top -o %MEM # 按内存排序 htop # 交互式查看进程资源占用 ``` - 确认是否为Java进程(如`java`或`tomcat`)占用过高内存[^2]。 2. **JVM内置工具分析** - 使用`jstat`监控GC行为: ```bash jstat -gc <pid> 1000 # 每秒输出一次GC统计 ``` 关注`FGC`(Full GC次数)和`FGCT`(Full GC耗时),频繁Full GC可能表明内存泄漏或堆配置不合理。 - 使用`jcmd`生成堆内存快照: ```bash jcmd <pid> GC.heap_dump /path/to/dump.hprof ``` #### 二、深入诊断内存泄漏 1. **堆转储分析(Heap Dump)** - 生成堆转储文件: ```bash jmap -dump:live,format=b,file=/path/to/dump.hprof <pid> ``` - 使用工具(如Eclipse MAT或JVisualVM)分析`dump.hprof`,重点关注: - **Dominator Tree**:查看占用内存最大的对象。 - **Histogram**:统计对象数量和大小,排查异常增长的类(如`HashMap$Node`或自定义类)。 2. **动态诊断工具** - **Arthas实时监控**: ```bash dashboard # 查看实时内存、线程、GC状态 heapdump /path/to/dump.hprof # 动态生成堆转储 ``` - 使用`monitor`命令跟踪方法调用: ```bash monitor -c 10 com.example.Service * # 每10秒统计一次方法调用 ``` 结合引用[3],需注意OOM堆栈可能仅反映“最后一根稻草”,需综合多个工具结果定位根因。 #### 三、优化与解决 1. **JVM参数调优** - 调整堆大小(如`-Xmx4g -Xms4g`)和垃圾回收器(如G1GC): ```bash java -Xmx4g -XX:+UseG1GC -jar app.jar ``` - 添加OOM时自动生成堆转储: ```bash -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps ``` 2. **代码级优化** - 修复内存泄漏:如未关闭的数据库连接(`Connection`)、流(`InputStream`)或静态集合缓存。 - 优化数据结构:避免高频创建大对象,使用弱引用(`WeakReference`)或缓存框架(如Caffeine)。 3. **第三方库与框架检查** - 排查框架(如Spring)的上下文未释放问题,或ORM工具(如Hibernate)的懒加载异常。 #### 四、验证与预防 1. **压力测试** 使用JMeter或Gatling模拟高负载,观察内存增长是否正常。 2. **持续监控** 集成APM工具(如Prometheus + Grafana)监控堆内存、GC频率等指标。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值