JVM 常见线上问题 → CPU 100%、内存泄露 问题排查
开心一刻

明明是个小 bug,但就是死活修不好,我特么心态崩了......
前言
后文会从 Windows、Linux 两个系统来做示例展示,有人会有疑问了:为什么要说 Windows 版的 ? 目前市面上还是有很多 Windows 服务器的,应用于传统行业、政府结构、医疗行业 等等;两个系统下的情况都演示下,有备无患
后文中用到了两个工具:Processor Explorer、MAT,它们是什么,有什么用,怎么用,本文不做介绍,不知道的小伙伴最好先去做下功课
cpu 100%
下面的示例中, cpu 的占有率没到 100%,只是比较高,但是排查方式是一样的,希望大家不要钻牛角尖
Windows
1、找到 cpu 占有率最高的 java 进程号

PID: 20260
2、根据进程号找到 cpu 占有率最高的线程号
双击刚刚找到的 java 进程

线程号: 15900 ,转成十六进制: 3e1c
3、利用 jstack 生成虚拟机中所有线程的快照
命令: jstack -l {pid} > {path}

文件路径: D:\20260.stack
4、线程快照分析
我们先浏览下快照内容

内容还算比较简洁,线程快照格式都是统一的,我们以一个线程快照简单说明下
"main" #1 prio=5 os_prio=0 tid=0x0000000002792800 nid=0x3e1c runnable [0x00000000025cf000]

我们前面找到占 cpu 最高的线程号: 15900 ,十六进制: 3e1c ,用 3e1c 去快照文件里面搜一下

自此,找到问题

Linux
排查方式与 Windows 版一样,只是命令有些区别
1、找到 cpu 占有率最高的 java 进程号
使用命令: top -c 显示运行中的进程列表信息, shift + p 使列表按 cpu 使用率排序显示

PID = 2227 的进程,cpu 使用率最高
2、根据进程号找到 cpu 占有率最高的线程号
使用命令: top -Hp {pid} ,同样 shift + p 可按 cpu 使用率对线程列表进行排序

PID = 2228 的线程消耗 cpu 最高,十进制的 2228 转成十六进制 8b4
3、利用 jstack 生成虚拟机中所有线程的快照

4、线程快照分析
分析方式与 Windows 版一致,我们可以把 2227.stack 下载到本地进行分析,也可直接在 Linux 上分析
在 Linux 上分析,命令: cat 2227.stack |grep '8b4' -C 5

至此定位到问题

不管是在 Windows 下,还是在 Linux 下,排查套路都是一样的

内存泄露
同样的,Windows、Linux 各展示一个示例
Windows
1、找到内存占有率最高的进程号 PID

第一眼看上去, idea 内存占有率最高,因为我是以 idea 启动的 java 进程;idea 进程我们无需关注,我们找到内存占有率最高的 java 的 PID: 10824
2、利用 jmap 生成堆转储快照
命令: jmap -dump:format=b,file={path} {pid}

dump 文件路径: D:\heapdump_108244.hprof
3、利用 MAT 分析 dump 文件
MAT:Memory Analyzer Tool,是针对 java 的内存分析工具;下载地址:

选择对应的版本,下载后直接解压;默认情况下,mat 最大内存是 1024m ,而我们的 dump 文件往往大于 1024m,所以我们需要调整,在 mat 的 home 目录下找到 MemoryAnalyzer.ini ,将 -Xmx1024m 修改成大于 dump 大小的空间, 我把它改成了 -Xmx4096m
接着我们就可以将 dump 文件导入 mat 中,开始 dump 文件的解析

解析是个比较漫长的过程,我们需要耐心等待

解析完成后,我们可以看到如下概况界面

各个窗口的各个细节就不做详细介绍了,有兴趣的可自行去查阅资料;我们来看看几个图:饼状图、直方图、支配树、可疑的内存泄露报告
饼状图

可以看出, com.lee.schedule.Schedule 对象持有 1G 内存,肯定有问题
直方图

我们看下 Person 定义

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Person { private String name;
private Integer age; }
可想而知,上图标记的几项都与 Person 有关
支配树

这就非常直观了,Schedule 中的 ArrayList 占了 99.04% 的大小
可疑的内存泄露报告

通过这些数据,相信大家也能找到问题所在了

Linux
排查方式与 Windows 一样,只是有稍许的命令区别
1、找到内存占有率最高的进程号
使用命令: top -c 显示运行中的进程列表信息, shift + m 按内存使用率进行排序

进程号: 2527
2、利用 jmap 生成堆转储快照
命令: jmap -dump:format=b,file={path} {pid}

堆转储快照文件路径: /opt/heapdump_2527.hprof
3、利用 MAT 分析堆转储快照
将 heapdump_2448.phrof 下载到本地,利用 MAT 进行分析;分析过程与 Windows 版完全一致

自此,定位到问题
Windows 下与 Linux 下,排查流程是一样的

总结
JVM 常用命令
jps:列出正在运行的虚拟机进程
jstat:监视虚拟机各种运行状态信息,可以显示虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据
jinfo:实时查看和调整虚拟机各项参数
jmap:生成堆转储快照,也可以查询 finalize 执行队列、Java 堆和永久代的详细信息
jstack:生成虚拟机当前时刻的线程快照
jhat:虚拟机堆转储快照分析工具
与 jmap 搭配使用,分析 jmap 生成的堆转储快照,与 MAT 的作用类似
排查步骤
1、先找到对应的进程: PID
2、生成线程快照 stack (或堆转储快照: hprof )
3、分析快照(或堆转储快照),定位问题
内存泄露、内存溢出和 CPU 100% 关系

常用 JVM 性能检测工具
Eclipse Memory Analyer、JProfile、JProbe Profiler、JVisualVM、JConsole、Plumbr
参考
面试官:如果你们的系统 CPU 突然飙升且 GC 频繁,如何排查?
JVM 常见线上问题 → CPU 100%、内存泄露 问题排查的更多相关文章
- 记一次线上服务CPU 100%的处理过程
告警 正在开会,突然钉钉告警声响个不停,同时市场人员反馈客户在投诉系统登不进了,报504错误.查看钉钉上的告警信息,几台业务服务器节点全部报CPU超过告警阈值,达100%. 赶紧从会上下来,SSH登录 ...
- Linux(2)---记录一次线上服务 CPU 100%的排查过程
Linux(2)---记录一次线上服务 CPU 100%的排查过程 当时产生CPU飙升接近100%的原因是因为项目中的websocket时时断开又重连导致CPU飙升接近100% .如何排查的呢 是通过 ...
- 线上服务 CPU 100%?一键定位 so easy!
转自: https://my.oschina.net/leejun2005/blog/1524687 摘要: 本文主要针对 Java 服务而言 0.背景 经常做后端服务开发的同学,或多或少都 ...
- 线上服务器CPU彪高的调试方式
原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/2fee7b91-f ...
- 【JVM】线上应用故障排查
高CPU占用 一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环. 根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障. 通过ps aux ...
- 通过jstack与jmap分析一次cpu打满的线上故障
一.发现问题 下面是线上机器的cpu使用率,可以看到从4月8日开始,随着时间cpu使用率在逐步增高,最终使用率达到100%导致线上服务不可用,后面重启了机器后恢复. 二.排查思路 简单分析下可能出问题 ...
- 系统运行缓慢,CPU 100%,以及Full GC次数过多问题的排查思路
前言 处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及Full GC次数过多的问题.当然,这些问题的最终导致的直观现象就是系统运行缓慢,并且有大量的报警. 本文主要针对系统运 ...
- 一次性搞清楚线上CPU100%,频繁FullGC排查套路
“ 处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及 Full GC 次数过多的问题. 当然,这些问题最终导致的直观现象就是系统运行缓慢,并且有大量的报警. 本文主要针对系统 ...
- 性能测试 | 系统运行缓慢,CPU 100%,Full GC次数过多问题排查
处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及Full GC次数过多的问题.当然,这些问题的最终导致的直观现象就是系统运行缓慢,并且有大量的报警.本文主要针对系统运行缓慢这 ...
随机推荐
- Android开发工程师面试题之handler详解。android程序员,android开发面试资料,详解
Message:消息:其中包含了消息ID,消息对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理 Handler:处理者:负责Message发送消息及处理.Handler ...
- Substance Painter教程
https://huke88.com/route/substance-painter.html?sem=baidu&kw=106738
- LuaBridge相关
http://www.cppblog.com/sunicdavy/archive/2013/12/07/204648.html https://segmentfault.com/a/119000000 ...
- Commando War (贪心)
Waiting for orders we held in the wood, word from the front never came By evening the sound of the g ...
- .net core3.1中实现简单的jwt认证
1.创建项目 使用visual studio创建一个名为JwtDemo的空项目,创建后如图 2.添加依赖项 在nuget包管理器中搜索 Microsoft.AspNetCore.Authenticat ...
- XmlAnalyzer1.00 源码
此工程用途:将xml同级属性/子节点按字母序排列重新输出. 源码下载: https://files.cnblogs.com/files/heyang78/XmlAnalyzer-20200526-1. ...
- leetcode刷题-75颜色分类
题目 给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中,我们使用整数 0. 1 和 2 分别表示红色.白色和蓝 ...
- MySql 实现数组根据下标获取对应值逻辑(array[i]逻辑)
在使用sql模拟一段java逻辑开发时碰到有一段逻辑为从字符串数组中根据下标获取对应的值的情况,百度了一番没有发现有类似功能的函数和现成的实现方式,经过调试弄出来了,记录下来,以备参考 //举例:从数 ...
- 干货:不同场景容器内获取客户端源IP的方法
摘要:客户端和容器服务器之间可能存在多种不同形式的代理服务器,那容器中如何获取到客户端真实的源ip呢? k8s已经成为当今容器化的标准,人们在享受容器带来的高效与便利的同时,也遇到一些烦恼:客户端和容 ...
- jmeter连接websocket wss
注:域名的默认端口号是443 1.先添加 WebSocket Open Connection:连接请求 2.再添加 WebSocket request-response Sampler:发送数据请求 ...