JVM内存泄露排查

本文介绍如何配置Tomcat以支持jconsole远程监控,包括设置jmxremote.password文件、修改catalina.sh参数及使用jconsole工具进行远程连接。同时介绍了利用jmap命令导出堆内存使用详情的方法,并通过MemoryAnalyzer工具分析潜在的内存泄露问题。

一:tomcat配置jconsole远程连接

1. jdk配置jmxremote.password

cp jmxremote.password.template jmxremote.password

2.jmxremote.password最后增加下列内容

monitorRole  QED

controlRole   password1111


3.tomcat服务bin/catalina.sh文件增加下列内容

JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=10.10.77.145 -Dcom.sun.management.jmxremote"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=12345"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=true"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"

JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.pwd.file=/home/jdk1.7.0_71/jre/lib/management/jmxremote.password"


10.10.77.145:当前tomcat服务机器的IP地址

12345:jconsole远程服务开放的端口

重启tomcat服务

二:jconsole工具远程连接

打开本地windows机器jdk安装目录bin/jconsole.exe工具



连接成功后出现下列图表



打开内存图表,我这里配置了CMS(concurrentMarkSweep)垃圾回收机制,所以显示的是CMS Old Gen,如果没配置CMS,应该是perm Old Gen(老年代区)。

当验证程序是否有内存泄露时,可以高并发的发送请求让服务程序一直在处理请求,可以看见下列的线条一直处于上升状态,当过一会儿后(时间可以长一点),点击执行GC,当内存使用率没有下降,则大致表明有内存泄露。这里可以让程序多调试几次,确定是否是由于内存泄露导致的。 如果程序无内存泄露,则正确的线条状态应如下所示。


三:jmap命令导出堆内存使用情况

jmap -heap pid       查看jvm堆内存使用情况

pid表示tomcat服务进程号,我配置了CMS垃圾回收机制,如果不配置,应该是 perm old generation,表示老年代堆区(jvm老年代区自行百度),如果是内存泄露,这里的内存会一直上升,直到100,就算调用gc,内存使用率也不会下降。



jmap -dump:format=b,file=./heap.bin pid  导出堆使用详情文件

pid表示tomcat服务进程号,为了更能排查那里出现了内存泄露,等到老年代内存使用率达到90%以上最佳,等一会就导出完成


四:MAT图形化查看堆内存使用情况

下载MemoryAnalyzer工具 http://www.eclipse.org/mat/downloads.php 点击打开链接

解压文件,打开mat目录下文件MemoryAnalyzer.exe工具


导入刚才堆内存文件heap.bin



打开详情,从上图可知类DubboFilterUtil有问题,从下图可知对象RequestInfo占用了太多的内存,剩下的就只需要定位到代码排查原因即可



排查 Java 应用中的内存泄漏问题时,Arthas 是一个非常强大的诊断工具。以下是一些常用的 Arthas 命令和方法,结合实际场景可以有效帮助定位内存问题。 ### 使用 Arthas 排查内存泄漏的常见步骤 #### 1. 查看 JVM 内存状态 使用 `memory` 命令查看当前 JVM 的内存状态,包括堆内存、非堆内存以及各个区域(如 Eden 区、Old 区)的使用情况。 ```bash memory ``` 该命令可以帮助识别是否有某个区域的内存持续增长,尤其是 Old 区的内存占用过高可能预示着潜在的内存泄漏。 #### 2. 监控内存变化趋势 使用 `dashboard` 命令实时监控 JVM 的整体运行状态,包括线程、内存、GC 等信息。 ```bash dashboard ``` 通过观察内存使用的趋势图,可以初步判断是否存在内存泄漏。如果内存使用量在一段时间内持续上升,可能意味着存在未被释放的对象。 #### 3. 分析对象直方图 使用 `jmap -histo` 命令查看堆中对象的分布情况,找出占用内存最多的类。 ```bash jmap -histo ``` 此命令会列出所有类的实例数量和总大小。重点关注实例数量或总大小异常高的类,这些类可能是内存泄漏的源头[^4]。 #### 4. 获取并分析堆转储文件 当怀疑有内存泄漏时,可以通过 `heapdump` 命令生成堆转储文件,然后使用 MAT (Memory Analyzer Tool) 进行详细分析。 ```bash heapdump /path/to/dumpfile.hprof ``` 生成的 `.hprof` 文件可以用 MAT 工具打开,进一步分析对象的引用链,找到未被释放的原因。 #### 5. 结合代码进行日志溯源 在定位到可疑对象后,结合应用程序的日志和代码逻辑,检查是否有不当的引用(如静态集合类持有大量对象、缓存未清理等)。根据代码逻辑修正问题,并验证修复效果。 ### 示例:分析特定类的实例 假设发现某个类 `com.example.MyObject` 占用了大量内存,可以通过 `object` 命令查看其具体实例: ```bash object <objectId> ``` 其中 `<objectId>` 是从 `jmap -histo` 或 `heapdump` 中获取的具体对象 ID。此命令可以帮助查看对象的详细信息及其引用关系。 ### 总结 Arthas 提供了多种手段来帮助排查 Java 应用中的内存泄漏问题,包括实时监控、对象直方图分析、堆转储文件生成等。通过这些工具的组合使用,可以有效地定位并解决内存泄漏问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值