原文地址:http://www.javatang.com

前一段时间上线的系统升级之后,出现了严重的高CPU的问题,于是开始了一系列的优化处理之中,现在将这个过程做成一个系列的文章。

基本概念

在对Java内存泄漏进行分析的时候,需要对jvm运行期间的内存占用、线程执行等情况进行记录的dump文件,常用的主要有thread dump和heap dump。

  • thread dump 主要记录JVM在某一时刻各个线程执行的情况,以栈的形式显示,是一个文本文件。通过对thread dump文件可以分析出程序的问题出现在什么地方,从而定位具体的代码然后进行修正。thread dump需要结合占用系统资源的线程id进行分析才有意义。
  • heap dump 主要记录了在某一时刻JVM堆中对象使用的情况,即某个时刻JVM堆的快照,是一个二进制文件,主要用于分析哪些对象占用了太对的堆空间,从而发现导致内存泄漏的对象。

上面两种dump文件都具有实时性,因此需要在服务器出现问题的时候生成,并且多生成几个文件,方便进行对比分析。下面我们先来说一下如何生成 thread dump。

使用jstack生成thread dump

当服务器出现高CPU的时候,首先执行 top -c 命令动态显示进程及占用资源的排行,如下图:

top后面的参数-c可以显示进程详细的信息。top命令执行的时候还可以执行一些快捷键:

  • 1 对于多核服务器,可以显示各个CPU占用资源的情况
  • shift+h 显示所有的线程信息
  • shift+w 将当前 top 命令的设置保存到 ~/.toprc 文件中,这样不用每次都执行快捷键了

以上图为例,pid为1503的进程占用了大量的CPU资源,接下来需要将占用CPU最高进程中的线程打印出来,可以用 top -bn1 -H -p <pid> 命令,执行结果如下:

上面 -bn1 参数的含义是只输出一次结果,而不是显示一个动态的结果。

我个人请喜欢用 ps -mp <pid> -o THREAD,tid,time | sort -k2r 命令查看,后面的sort参数根据线程占用的cpu比例进行排序,结果如下:

接下来我们清楚今天的主角 jstack,这是一个在JDK5开始提供的内置工具,可以打印指定进程中线程运行的状态,包括线程数量、是否存在死锁、资源竞争情况和线程的状态等等。有下面的几个常用的参数:

  • -l 长列表,打印关于锁的附加信息
  • -m 打印java和jni框架的所有栈信息

因为thread id在栈信息中是以十六进制的形式显示的,因此需要使用 printf "%x \n" <tid> 命令将现场id转成十六进制的值,然后执行 jstack -l <pid> | grep <thread-hex-id> -A 10 命令显示出错的堆栈信息,如下图:

上面命令中 -A 10 参数用来指定显示行数,否则只会显示一行信息。

这样通过上图,可以很快地定位到程序问题的代码,然后对代码进行分析和改进即可。注意:需要在多个时间段提出多个 Thread Dump信息,然后综合进行对比分析,单独分析一个文件是没有意义的。

生成shell文件

上面讲述了整个的分析过程,不过所有的命令就是实时的,所以最好创建一个shell脚本瞬间执行完成,下面对 当CPU飙高时,它在做什么 这篇文章中所提供的shell进行了改进如下:

#!/bin/bash
if [ $# -ne 1 ]; then
echo "usage: $0 <pid> [line-number]"
exit 1
fi # java home
if test -z $JAVA_HOME
then
JAVA_HOME='/usr/local/jdk'
fi #pid
pid=$1
# checking pid
if test -z "$($JAVA_HOME/bin/jps -l | cut -d '' -f 1 | grep $pid)"
then
echo "process of $pid is not exists"
exit
fi #line number
if test -z $linenum
then
linenum=10
fi stackfile=stack$pid.dump
threadsfile=threads$pid.dump # generate java stack
$JAVA_HOME/bin/jstack -l $pid >> $stackfile
ps -mp $pid -o THREAD,tid,time | sort -k2r | awk '{if ($1 !="USER" && $2 != "0.0" && $8 !="-") print $8;}' | xargs printf "%x\n" >> $threadsfile
tids="$(cat $threadsfile)"
for tid in $tids
do
echo "------------------------------ ThreadId ($tid) ------------------------------"
cat $stackfile | grep 0x$tid -A $linenum
done rm -f $stackfile $threadsfile

下一篇文章将要讲述如何对jstack生成的文件进行分析

Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息的更多相关文章

  1. Java内存泄漏分析系列之四:jstack生成的Thread Dump日志线程状态

    原文地址:http://www.javatang.com Thread Dump日志的线程信息 以下面的日志为例: "resin-22129" daemon prio=10 tid ...

  2. Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析

    原文地址:http://www.javatang.com 一个典型的thread dump文件主要由一下几个部分组成: 上图将JVM上的线程堆栈信息和线程信息做了详细的拆解. 第一部分:Full th ...

  3. Java内存泄漏分析系列之五:常见的Thread Dump日志案例分析

    原文地址:http://www.javatang.com 症状及解决方案 下面列出几种常见的症状即对应的解决方案: CPU占用率很高,响应很慢 按照<Java内存泄漏分析系列之一:使用jstac ...

  4. Java内存泄漏分析系列之六:JVM Heap Dump(堆转储文件)的生成和MAT的使用

    原文地址:http://www.javatang.com JVM Heap Dump(堆转储文件)的生成 正如Thread Dump文件记录了当时JVM中线程运行的情况一样,Heap Dump记录了J ...

  5. Java内存泄漏分析系列之三:jstat命令的使用及VM Thread分析

    原文地址:http://www.javatang.com 使用jstat命令 当服务器CPU100%的时候,通过定位占用资源最大的线程定位到 VM Thread: "VM Thread&qu ...

  6. Java内存泄漏分析系列之七:使用MAT的Histogram和Dominator Tree定位溢出源

    原文地址:http://www.javatang.com 基础概念 先列出几个基础的概念: Shallow Heap 和 Retained Heap Shallow Heap表示对象本身占用内存的大小 ...

  7. Java内存泄漏分析与解决方案

    Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可是布署到远端就会出现内存无限制的增长,最后系统瘫痪,那么如何最快最好的检测程序的稳定性,防止系统崩盘,作者用自已的亲身经历 ...

  8. Java内存泄漏分析和预防

    1. 什么是内存泄漏?有什么危害 书面说法: 内存泄漏:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着. 在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个 ...

  9. Java内存泄漏分析

    https://www.javatang.com/archives/2017/11/08/11582145.html?tdsourcetag=s_pcqq_aiomsg

随机推荐

  1. Spark:scala集合转化为DS/DF

    scala集合转化为DS/DF case class TestPerson(name: String, age: Long, salary: Double) val tom = TestPerson( ...

  2. 【FAQ系列】关于SQL_Errno:1677导致主从复制中断的思考和实践

    1.简单介绍该错误发生的背景: 1) 数据库版本:MySQL5.7.19 2) 对一个大表修改字段类型DDL(将主键id int变为bigint),为了不影响主库业务,先在从库上执行DDL操作,然后通 ...

  3. Windows使用Gitblit搭建Git服务器

    安装之前需确定安装JAVA运行环境. 下载安装 首先到 Gitblit官网 下载安装包.此处使用的版本是1.8.0. 将解压得到的gitblit-1.8.0文件夹放于C:\gitServer目录下. ...

  4. No Java compiler available

    <!-- 添加tomcat支持 --> <dependency> <groupId>org.springframework.boot</groupId> ...

  5. Java面试题1--关键字

    1. final关键字有哪些用法? 修饰类.方法和变量. (1) final变量是只读的,不允许改变其引用,与static共用可声明常量.JVM会对final变量进行优化,比如常量折叠. (2) fi ...

  6. angualar2——八大组成

    Angular2 模块 理解: Angular 应用是模块化的,并且 Angular 有自己的模块系统,它被称为 Angular 模块或 NgModules. 组件 组件是一个项目主干,一个模块由多个 ...

  7. [LeetCode] Find K Closest Elements 寻找K个最近元素

    Given a sorted array, two integers k and x, find the k closest elements to x in the array. The resul ...

  8. [LeetCode] Non-negative Integers without Consecutive Ones 非负整数不包括连续的1

    Given a positive integer n, find the number of non-negative integers less than or equal to n, whose ...

  9. c++类与对象(1)——构造,复制构造函数

    CPP的类与对象: 当我们定义一个基本类型变量时,方法如下: int p; #定义一个int类型变量 bool b; #定义一个bool类型变量 float c ; #定义一个float类型变量 显然 ...

  10. Mac 下安装 MySQL 经历

    1.使用 homebrew 安装: brew install mysql 结果报错: $ brew install mysql ==> Downloading http://dev.mysql. ...