通过jstack与jmap分析一次线上故障
一、发现问题
下面是线上机器的cpu使用率,可以看到从4月8日开始,随着时间cpu使用率在逐步增高,最终使用率达到100%导致线上服务不可用,后面重启了机器后恢复。

二、排查思路
简单分析下可能出问题的地方,分为5个方向:
1.系统本身代码问题
2.内部下游系统的问题导致的雪崩效应
3.上游系统调用量突增
4.http请求第三方的问题
5.机器本身的问题
三、开始排查
1.查看日志,没有发现集中的错误日志,初步排除代码逻辑处理错误。
2.首先联系了内部下游系统观察了他们的监控,发现一起正常。可以排除下游系统故障对我们的影响。
3.查看provider接口的调用量,对比7天没有突增,排除业务方调用量的问题。
4.查看tcp监控,TCP状态正常,可以排除是http请求第三方超时带来的问题。
5.查看机器监控,6台机器cpu都在上升,每个机器情况一样。排除机器故障问题。
即通过上述方法没有直接定位到问题。
四、解决方案
1.重启了6台中问题比较严重的5台机器,先恢复业务。保留一台现场,用来分析问题。
2.查看当前的tomcat线程pid

3.查看该pid下线程对应的系统占用情况。top -Hp 384

4.发现pid 4430 4431 4432 4433 线程分别占用了约40%的cpu
5.将这几个pid转为16进制,分别为114e 114f 1150 1151
6.下载当前的java线程栈 sudo -u tomcat jstack -l 384>/1.txt
7.查询5中对应的线程情况,发现都是gc线程导致的

8.dump java堆数据
sudo -u tomcat jmap -dump:live,format=b,file=/dump201612271310.dat 384
9.使用MAT加载堆文件,可以看到javax.crypto.JceSecurity对象占用了95%的内存空间,初步定位到问题。
MAT下载地址:http://www.eclipse.org/mat/


10.查看类的引用树,看到BouncyCastleProvider对象持有过多。即我们代码中对该对象的处理方式是错误的,定位到问题。
五、代码分析
我们代码中有一块是这样写的

这是加解密的功能,每次运行加解密都会new一个BouncyCastleProvider对象,放倒Cipher.getInstance()方法中。
看下Cipher.getInstance()的实现,这是jdk的底层代码实现,追踪到JceSecurity类中

verifyingProviders每次put后都会remove,verificationResults只会put,不会remove.

看到verificationResults是一个static的map,即属于JceSecurity类的。
所以每次运行到加解密都会向这个map put一个对象,而这个map属于类的维度,所以不会被GC回收。这就导致了大量的new的对象不被回收。
六、代码改进
将有问题的对象置为static,每个类持有一个,不会多次新建。

七、本文总结
遇到线上问题不要慌,首先确认排查问题的思路:
- 查看日志
- 查看CPU情况
- 查看TCP情况
- 查看java线程,jstack
- 查看java堆,jmap
- 通过MAT分析堆文件,寻找无法被回收的对象
通过jstack与jmap分析一次线上故障的更多相关文章
- JAVA 线上故障排查套路,从 CPU、磁盘、内存、网络到GC 一条龙!
线上故障主要会包括cpu.磁盘.内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍. 同时例如jstack.jmap等工具也是不囿于一个方面的问题的, ...
- JVM 线上故障排查
JVM 线上故障排查 Linux 1.1 CPU 1.2 内存 1.3 存储 1.4 网络 一.CPU 飚高 寻找原因 二.内存问题排查 三.一般排查问题的方法 四.应用场景举例 4.1 怎么查看某个 ...
- JAVA线上故障排查手册-(推荐)
参考:https://fredal.xin/java-error-check?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=tout ...
- JVM线上故障初步简易排查
线上故障主要包括cpu 磁盘 内存 网络等问题 依次排查 1.cpu 1) 先用ps找到进程pid 2) top -H -p pid 找到cpu占用高的线程 3)printf '%x\n' pid 获 ...
- JVM 线上故障排查基本操作--CPU飙高
JVM 线上故障排查基本操作 CPU 飚高 线上 CPU 飚高问题大家应该都遇到过,那么如何定位问题呢? 思路:首先找到 CPU 飚高的那个 Java 进程,因为你的服务器会有多个 JVM 进程.然后 ...
- 通过jstack与jmap分析一次cpu打满的线上故障
一.发现问题 下面是线上机器的cpu使用率,可以看到从4月8日开始,随着时间cpu使用率在逐步增高,最终使用率达到100%导致线上服务不可用,后面重启了机器后恢复. 二.排查思路 简单分析下可能出问题 ...
- JVM 线上故障排查基本操作
# 前言 对于后端程序员,特别是 Java 程序员来讲,排查线上问题是不可避免的.各种 CPU 飚高,内存溢出,频繁 GC 等等,这些都是令人头疼的问题.楼主同样也遇到过这些问题,那么,遇到这些问题该 ...
- 从一次线上故障思考Java问题定位思路
问题出现:现网CPU飙高,Full GC告警 CGI 服务发布到现网后,现网机器出现了Full GC告警,同时CPU飙高99%.在优先恢复现网服务正常后,开始着手定位Full GC的问题.在现场只能够 ...
- Java程序线上故障排查
目录 一.Linux 内存和cpu 网络 磁盘 /proc文件系统 二.JVM Java堆和垃圾收集器 gc日志分析 JVMTI介绍 Attach机制 java自带工具 三.三方工具 jprofile ...
随机推荐
- 一个具有缓存数据功能的HttpWebRequest工具类
背景:一个公共站点中的数据,供其它子站点共享,为了提高性能,简单实现了Http 1.1的缓存功能 特点:可以缓存Html数据到内存中;缓存具有过期时间;缓存过期后,通过再确认的方式来决定是否更新缓存; ...
- MySQL的replace方法
mysql中replace函数直接替换mysql数据库中某字段中的特定字符串,不再需要自己写函数去替换,用起来非常的方便,mysql 替换函数replace()Update `table_name` ...
- Java中list如何利用遍历进行删除操作
转: Java中list如何利用遍历进行删除操作 2018年03月31日 10:23:41 Little White_007 阅读数:3874 Java三种遍历如何进行list的便利删除: 1.f ...
- C语言复习---选择法排序
选择排序也是一种简单直观的排序算法 它的工作原理很容易理解:初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列:然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾. ...
- elementUI下拉框错误记录
选择广东省深圳市,保存,再编辑是这样效果 原因 保存的那张表相关字段为字符串,而生成下拉框该字段是整数,两者改成一致即可 修改后
- js调试系列: 断点与动态调试[基础篇]
js调试系列目录: - 额,我说的不是张敬轩的 断点 这首歌,是调试用到的断点,进入正题吧. 昨天留的课后练习 1. 分析 votePost 函数是如何实现 推荐 的.其实我们已经看到了源码,只要读下 ...
- 第7月第26天 iOS httpserver
1. cocoahttpserver 1)httpserver [httpServer start:&error] 2)HTTPConnection [newConnection start] ...
- Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7)【转】
原文地址:Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.c ...
- Shell脚本中实现切换用户并执行命令操作【转】
第一种方法 cat test.sh #!/bin/bashsu - test <<EOFpwd;exit;EOF 执行结果图: 第二种方法 当然也可以用下面的命令来执行 复制代码代码如下: ...
- PHP中冒号、endif、endwhile、endfor使用介绍
我们经常在wordpress一类博客程序的模板里面看到很多奇怪的PHP语法,比如: 复制代码代码如下: <?php if(empty($GET_['a'])): ?> <font c ...