记录一次jvm内存泄露的问题
前些天,运维告诉我刚上线的java服务占用CPU过高。
以下是发现解决问题的具体流程。
1:通过#top命令查看,我的java服务确实把CPU几乎占满了,如图

可看到18400这个进程CPU占用达到了1200%,这确实不太正常,那么我们接下来分析到底哪些线程占用了CPU
2:通过#top -Hp 18400这条命令我们可以看到这个进程中线程的情况,部分截图如下。

通过截图可以看到,前面的线程占用的CPU是比较高的,那我们就具体分析这些线程
3:我们通过#jstack 18400>18400.txt命令将这个java进程的线程栈给抓出来,可以多抓几次做个对比。
我们以18414这个线程为例,将它转成16进制,linux可以用终端通过命令#printf "%x" 18414将线程id转为16进制为47ee,那么我们接下来在文件里找47ee这个线程在干什么,部分截图如下

我们可以看到47ee是个垃圾回收线程;我们对其他占用CPU高的线程做相同的操作,发现都是GC线程。说明这个java服务一直在GC,这很不正常。那么我们接下来分析GC情况。
4:我们通过命令#jstat -gcutil 18400 1000 100来查看接下开的GC情况,部分截图如下

是不是很直观,通过YGC这一列发现younggc次数没有增加,但是通过FGC这一列看到fullgc的次数一直在增加,可怕的是老年代并没有回收(通过O这列看出来)。
这时候你是不是想起来了一个名词:内存泄露。没错,接下来我们就需要分析哪里出现了内存泄露。
5:我们可以通过#jmap -dump:live,format=b,file=18400.dump 18400将这个进程当前的堆给dump下来。注意,这个文件可以看成是堆的快照,所以当前堆有多大,dump下来的问价差不多也有多大。我dump下来的差不多2G。
有了这个文件,我们需要分析,你可以用命令jhat分析,当然我们常用的是功能比较强大的图形化工具,如JDK自带的visualvm,也可以用第三方的JProfiler(我用的是这个),如果你用Eclipse,也可以安装MAT插件。这些工具都能分析堆dump文件。
需要注意的是,由于dump文件可能比较大,所以所需分析工具的内存也比较大,最好在性能比较好的机器上进行分析。
下面是我的JProfiler分析的部分截图

是不是很直观,有个对象占了97%的内存。那么接下来需要分析这个对象在哪产生,在哪被引用。我这里很明显是这个LinkedList占用了全部空间,那么就去分析这个LinkedList里面都存了些什么,这些有可能需要结合你的代码,我就不细说了。
我分析出来的是ElasticSearch的客户端工具JestClient的异步请求队列太长了,整个List里面的节点都是异步请求信息,大概生成了10多万个。消费不及时又无法被回收,所以产生了内存泄露。(注意,使用线程池也有可能会出现这个情况)
6:分析出了原因,那么接下来就解决问题。因为我当时急着上线,不知道JestClient的异步队列长度怎么配,就暂时把异步改成了同步,暂时解决了这个问题。上线后查看CPU,垃圾回收等情况确实恢复了正常。
总的来说,上面的6步是一个完整的分析解决jvm虚拟机内存泄露的流程,当然可能有不完善的地方,但大体思路是没错的。
通过这篇文章,我们可以总结出以下几点:
1:如何分析Java服务占用CPU过高的问题
2:使用Java各种队列的时候一定要关注队列的长度,预防内存泄露。
3:最好熟悉一下jvm的内存模型
记录一次jvm内存泄露的问题的更多相关文章
- 记录一次Tomcat内存泄露原因的追溯
现象:WEB无法访问.SSH无法登陆.桌面登陆验证失败. 重启服务器后登陆正常. cat /var/log/message显示root用户创建了2000多个sessions后显示内存不足. 进入tom ...
- Java JVM 内存泄漏--全解析和处理办法 [ 转载 ]
Java JVM 内存泄露——全解析和处理办法 [转载] @author 小筐子 @address http://www.jianshu.com/p/bf159a9c391a JA ...
- FastMM内存泄露
转自:http://www.2ccc.com/article.asp?articleid=4879FastMM是非常优秀的内存管理器,但是从FastMM4Options.inc中找到合适自已程序的选项 ...
- 排查JVM内存泄漏的命令
1. jps 使用 jps -l -m 获取到当前jvm进程的pid,通过上述命令获取到了服务的进程号 jps(JVM Process Status Tool):显示指定系统内所有的HotSpot虚拟 ...
- JVM内存结构、参数调优和内存泄露分析
1. JVM内存区域和参数配置 1.1 JVM内存结构 Java堆(Heap) Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建.此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都 ...
- JVM 常见线上问题 → CPU 100%、内存泄露 问题排查
开心一刻 明明是个小 bug,但就是死活修不好,我特么心态崩了...... 前言 后文会从 Windows.Linux 两个系统来做示例展示,有人会有疑问了:为什么要说 Windows 版的 ? 目前 ...
- JVM内存管理概述与android内存泄露分析
一.内存划分 将内存划分为六大部分,分别是PC寄存器.JAVA虚拟机栈.JAVA堆.方法区.运行时常量池以及本地方法栈. 1.PC寄存器(线程独有):全称是程序计数寄存器,它记载着每一个线程当前运行的 ...
- 我进行jvm内存调优的一些记录
jvm内存调优的一些记录 java内存调优的方法和过程 可以使用 jmap -heap pid号 查看,例如pid是9300,执行的结果可能是这样的. root@ubuntu:~# jmap -hea ...
- Java内存泄露监控工具:JVM监控工具介绍【转】
jstack?-- 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程 ...
随机推荐
- axios跨域访问eggjs的坑egg-cors egg-passport passport-local session传递问题
在同一机器上写前端和后端,前端使用webpack-dev-server启动,后端直接在eggjs项目目录下使用npm run dev启动,这种情况下,前端访问后端就是跨域访问.eggjs提供了一个跨域 ...
- Linux系统下安装zookeeper教程
环境: 1.VMware® Workstation 12 Pro 2.CentOS7 3.zookeeper-3.4.6 安装步骤 1.下载zookeeper 本文使用的zookeeper下载地址如下 ...
- Day004_Linux基础_基础命令之tar打包解包
基础命令之 打包,和解包. tar zcvf 打包的参数 tar zcvf /tmp/etc.tar.gz /etc 将/etc/下的文件压缩成一个压缩包 z 通过gzip工具进行压缩 c 表示 ...
- IDEA中全局搜索不起作用,解决办法
众所周知IDEA中全局搜索的快捷键是Ctrl+Shift+F,但是今天却碰到了用不了的情况,其实软件坏了的可能性很小,那就要从外部再来找原因,查看自己开的软件,一一查看快捷键,看是否是快捷键冲突: 1 ...
- Vue中的slot(占坑,预留位置)
Vue中的slot(占坑,预留位置) 子模板不使用slot 子模板使用slot 子模板使用使用name属性,且传递data 文件名:Slots.vue //slot组件 <template> ...
- 微信小程序集成腾讯云 IM SDK
微信小程序集成腾讯云 IM SDK 1.背景 因业务功能需求需要接入IM(即时聊天)功能,一开始想到的是使用 WebSocket 来实现这个功能,然天意捉弄(哈哈)服务器版本太低不支持 wx 协议(也 ...
- Netty源码分析 (九)----- 拆包器的奥秘
Netty 的解码器有很多种,比如基于长度的,基于分割符的,私有协议的.但是,总体的思路都是一致的. 拆包思路:当数据满足了 解码条件时,将其拆开.放到数组.然后发送到业务 handler 处理. 半 ...
- Python获取列表中的最后一个或者倒数第几个的方案
print(members[3]) 灵魂所在“ - (负号 )” 我们先来创建一个列表,和php中的数组一样. members = ['张三','李四','王五','芳芳','小明','小王'] 按照 ...
- CentOS7升级OpenSSL到1.1.1
首先下载解压最新的 OpenSSL wget https://github.com/openssl/openssl/archive/OpenSSL_1_1_1-stable.zip unzip Ope ...
- 5分钟学linux命令之split
情景介绍 平时工作中,我习惯使用rz从本地上传文件到服务器,sz从服务器下载文件到本地,但对传输文件大小有限制,例如排查线上jvm的问题,需要生成了dump文件,可能有10G大,超过了限制,怎么下载呢 ...