线上系统假死、内存溢出分析常用命令

  1. 查询jvm进程占用的cpu,内存

pidstat –p 进程号或者用命令:top –p 进程号

 

示例:

top –p 10461

线上系统假死、内存溢出分析常用命令_第1张图片

说明:

系统运行时间和平均负载:

top - 11:25:12(当前时间) up 28 days, 42 min(系统已运行时间), 13 users(当前登录用户数),  load average: 0.98, 1.00, 1.02(5分钟,10分钟,15分钟的负载情况)

 

任务(进程):

Tasks:   1 total(系统总进程数),   0 running(运行中的进程数),   1 sleeping(休眠中的进程数),   0 stopped(停止的进程数),   0 zombie(僵尸状态的进程数)

 

CPU状态:

Cpu(s):  0.6%us(运行未调整优先级的)用户进程的CPU的百分比,  0.3%sy(运行内核进程的CPU的百分比),  0.0%ni(运行已调整优先级的用户进程的CPU的百分比), 99.0%id(空闲CPU的百分比),  0.0%wa(用于等待IO完成的CPU的百分比),  0.0%hi(处理硬件中断的CPU的百分比),  0.0%si(处理软件中断的CPU的百分比),  0.0%st(虚拟机占用的百分比)

 

物理内存使用情况:

Mem:  32837532k total(全部可用内存), 22419516k used(已使用内存), 10418016k free(空闲内存),    49372k buffers(缓冲内存)

虚拟内存(交换空间)使用情况:

Swap:  16490492K total(全部可用内存),0k used(已使用内存), 16490492k free(空闲内存), 423252k cached(缓冲交换空间)

 

PID   USER   PR  NI  VIRT  RES   SHR   S  %CPU  %MEM  TIME+    COMMAND

10461  tst_cps   20   0  9175m  606m  15m  S  0.7     1.9     63:43.53 

Java

PID:进程ID,进程的唯一标识符

USER:进程所有者的实际用户名。

PR:进程的调度优先级。这个字段的一些值是’rt’。这意味这这些进程运行在实时态。

NI:进程的nice值(优先级)。越小的值意味着越高的优先级。

VIRT:进程使用的虚拟内存。

RES:驻留内存大小。驻留内存是任务使用的非交换物理内存大小。

SHR:SHR是进程使用的共享内存。

S:这个是进程的状态。它有以下不同的值:D – 不可中断的睡眠态。R – 运行态。S – 睡眠态。T – 被跟踪或已停止。Z – 僵尸态。

%CPU:自从上一次更新时到现在任务所使用的CPU时间百分比。

%MEM:进程使用的可用物理内存百分比。

TIME+:任务启动后到现在所使用的全部CPU时间,精确到百分之一秒。

COMMAND:运行进程所使用的命令。

 

2. 查看进程内占用cpu和内存最多的线程

ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid

示例:

top –Hp 7122

线上系统假死、内存溢出分析常用命令_第2张图片

 

3. 根据线程号打印线程堆栈

jstack 进程号|grep 线程号的十六进制

   可以添加“> stack.log”到文件中

示例:

对7147线程号打印堆栈,只取20行查看

[tst_cps@futsthost02 ~]$ jstack 7122|grep 1beb -A 20

"Service Thread" daemon prio=10 tid=0x00007fb8ec112800 nid=0x1beb runnable [0x0000000000000000]

   java.lang.Thread.State: RUNNABLE

 

4. 查找WAITING或者deadlock或者Blocked的线程堆栈

[cps_alarm@rac2 ~]$ jstack 36346|grep "LOCKED" -A 10

[cps_alarm@rac2 ~]$ jstack 36346|grep "deadlock" -A 10

 

5. 用jstat查看GC和PermGen相关的信息

根据jstat统计的维度不同,可以使用如下表中的选项进行不同维度的统计,不同的操作系统支持的选项可能会不一样,可以通过-options选项,查看不同操作系统所支持选项,如:

Option

Displays...

class

用于查看类加载情况的统计

compiler

用于查看HotSpot中即时编译器编译情况的统计

gc

用于查看JVM中堆的垃圾收集情况的统计

gccapacity

用于查看新生代、老生代及持久代的存储容量情况

gccause

用于查看垃圾收集的统计情况(这个和-gcutil选项一样),如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因。

gcnew

用于查看新生代垃圾收集的情况

gcnewcapacity

用于查看新生代的存储容量情况

gcold

用于查看老生代及持久代发生GC的情况

gcoldcapacity

用于查看老生代的容量

gcpermcapacity

用于查看持久代的容量

gcutil

用于查看新生代、老生代及持代垃圾收集的情况

printcompilation

HotSpot编译方法的统计

 

示例:

[cps_alarm@rac2 ~]$ jstat -class 36346

Loaded  Bytes  Unloaded  Bytes     Time  

   399   788.1        0     0.0       0.05

Loaded:加载的类的数量

Bytes:加载的类的大小,单位为Kb

Unloaded:卸载的类的数量

Bytes:卸载的类的大小,单位为Kb

Time:花在类的加载和卸载的时间

 

[cps_alarm@rac2 ~]$ jstat -gc 36346

S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT  

32768.0 32768.0  0.0    0.0   196608.0 15729.1   262144.0     0.0       -      -      -      -         0    0.000   0      0.000    0.000

线上系统假死、内存溢出分析常用命令_第3张图片

 

6. 使用jmap统计内存使用情况

导出java程序对象统计信息:

jmap -histo pid > /home/tst_zcgl/2.txt

导出dump文件

jmap -dump:format=b,file=/home/tst_zcgl/3.hprof 3941

 

示例:

[cps_alarm@rac2 ~]$ jmap -histo 36346

 

 num     #instances         #bytes  class name

----------------------------------------------

   1:             8       15642976  [I

   2:          5908         761392 

   3:          5908         676328 

   4:           399         459152 

   5:           362         283328 

   6:           399         273672 

   7:          1866         202056  [C

   8:          1070         156128  [B

   9:           461          45224  java.lang.Class

  10:           679          43952  [[I

  11:           613          37352  [S

  12:          1474          35376  java.lang.String

  13:            45          24480 

  14:           333          15624  [Ljava.lang.Object;

  15:           119           8568  java.lang.reflect.Field

  16:             9           7056 

  17:           187           5984  java.io.File

 

7. 使用jinfo命令查看虚拟机配置信息

示例:jinfo pid

8. Jcmd命令-涵盖了jmap,jstack的命令

jcmd的常见用法:

  1. 堆直方图查看:查看系统中类统计信息GC.class_histogram
  2. 堆转储:导出堆信息GC.heap_dump
  3. 获取系统Properties内容VM.system_properties
  4. 获取启动参数VM.flags
  5. 获取所有性能相关数据PerfCounter.print
  6. 查看原生内存信息:jcmd process_id VM.native_memory summary

在项目中添加-XX:NativeMemoryTracking=detailJVM参数重启项目

8.1 列出当前运行的所有的虚拟机

[tst_cps@futsthost02 logs]$ jcmd -l

1254 sun.tools.jcmd.JCmd -l

7122 com.fuiou.cps.StartUp

8.2 列出虚拟机支持的命令

[tst_cps@futsthost02 logs]$ jcmd 7122 help

7122:

The following commands are available:

VM.native_memory

VM.commercial_features

GC.rotate_log

ManagementAgent.stop

ManagementAgent.start_local

ManagementAgent.start

Thread.print

GC.class_histogram

GC.heap_dump

GC.run_finalization

GC.run

VM.uptime

VM.flags

VM.system_properties

VM.command_line

VM.version

Help

8.3 统计原生内存

Jcmd显示的内存包括堆内内存、Code区域、通过unsafe.allocateMemoryDirectByteBuffer申请的内存,但是不包含其他Native CodeC代码)申请的堆外内存。

使用jcmd 14184 VM.native_memory detail可以看到内存地址空间。在分析内存泄露时,可能会用到这些地址空间。

[tst_cps@web1 ~]$ jcmd 14184 VM.native_memory

14184:

 

Native Memory Tracking:

 

Total:  reserved=900950KB(保留内存),  committed=787874KB(提交内存)

 

-                 Java Heap (reserved=655872KB, committed=590336KB)

                            (mmap: reserved=655872KB, committed=590336KB)

 

-                     Class (reserved=9870KB, committed=9870KB)(用于保存类的元数据的原生内存)

                            (classes #6732)(6732个类)

                            (malloc=9870KB, #4219)

 

-                    Thread (reserved=118902KB, committed=118902KB)

                            (thread #115)(115个线程)

                            (stack: reserved=118220KB, committed=118220KB)

                            (malloc=365KB, #470)

                            (arena=317KB, #230)

 

-                      Code (reserved=50423KB, committed=3171KB)(JIT代码缓存)

                            (malloc=503KB, #1422)

                            (mmap: reserved=49920KB, committed=2668KB)

 

-                        GC (reserved=33760KB, committed=33504KB)

                            (malloc=10384KB, #141)

                            (mmap: reserved=23376KB, committed=23120KB)

 

-                  Compiler (reserved=146KB, committed=146KB)(编译器自身操作使用的内存)

                            (malloc=48KB, #103)

                            (arena=98KB, #2)

 

-                  Internal (reserved=14214KB, committed=14182KB) (包括了directMemory)

                            (malloc=14182KB, #2367)

                            (mmap: reserved=32KB, committed=0KB)

 

-                    Symbol (reserved=9771KB, committed=9771KB) (保留字符串的引用和符号表引用)

                            (malloc=6439KB, #57283)

                            (arena=3332KB, #1)

 

-           Memory Tracking (reserved=7798KB, committed=7798KB)

                            (malloc=7798KB, #418)

 

-        Pooled Free Chunks (reserved=194KB, committed=194KB)

                            (malloc=194KB)

 

 

9. Pmap查看进程的内存映射信息

示例:

[cps_alarm@rac2 ~]$ pmap -x 4619|sort -k 3 -n –r(按照Rss降序排列)

 

total kB 18014124742943900   23444   13584

00007f7bc94dc000   11736    6892       0 r-x--  libjvm.so

00000000d8000000   21504    2452    2452 rw---    [ anon ]

00007f7bb8b92000    2340    2340    2340 rw---    [ anon ]

00007f7bc0987000    1792    1792       0 r--s-  rt.jar

00007f7bc1270000   48304    1600    1600 rw---    [ anon ]

00007f7bb8dde000    2044    1044    1044 rw---    [ anon ]

00007f7bc86f0000    1028    1028    1028 rw---    [ anon ]

00007f7bca251000     784     784     784 rw---  libjvm.so

00007f7bca356000    1576     588       0 r-x--  libc-2.12.so

00007f7bc8630000     556     556     556 rw---    [ anon ]

00007f7bc8047000     656     528     528 rw---    [ anon ]

00007f7bc0b47000    1752     472     472 rw---    [ anon ]

00000000e0000000  524288     452     452 rw---    [ anon ]

00007f7b70000000     392     344     344 rw---    [ anon ]

00007f7bc0033000    9552     336     336 rw---    [ anon ]

00007f7bc1000000    2496     256     256 rwx--    [ anon ]

00007f7bca315000     260     188     188 rw---    [ anon ]

00007f7bcae2e000    1032     116     116 rw---    [ anon ]

00007f7bcad20000     128     116       0 r-x--  ld-2.12.so

00007f7bc8c17000     164     112       0 r-x--  libjava.so

00007f7bb97e6000   41064     112     112 rw---    [ anon ]

00007f7bb94e5000    1016      92      92 rw---    [ anon ]

00007f7bb93e4000    1016      92      92 rw---    [ anon ]

 

找到可疑地址空间:在jcmd 进程号 VM.native_memory detail命令输出的地址空间中查找,如果没有考虑是native code分配地址空间引起。

可参看这篇文字:

https://mp.weixin.qq.com/s/cs92_dRqsn2_jHAtcEB57g

 

  1. Alibaba-dubbo官网提供的dump脚本

JAVA_HOME=/usr/java/jdk1.7.0_80 

OUTPUT_HOME=~/output 

DEPLOY_HOME=$1 

HOST_NAME=`hostname` 

 

DUMP_PIDS=`ps  --no-heading -C java -f --width 1000 | grep "$DEPLOY_HOME" |awk '{print $2}'` 

if [ -z "$DUMP_PIDS" ]; then 

    echo "The server $HOST_NAME is not started!" 

    exit 1; 

fi 

 

if [ ! -d $OUTPUT_HOME ]; then 

    mkdir $OUTPUT_HOME 

fi 

 

DUMP_ROOT=$OUTPUT_HOME/dump

if [ ! -d $DUMP_ROOT ]; then 

    mkdir $DUMP_ROOT 

fi 

 

DUMP_DATE=`date +%Y%m%d%H%M%S` 

DUMP_DIR=$DUMP_ROOT/dump-$DUMP_DATE 

if [ ! -d $DUMP_DIR ]; then 

    mkdir $DUMP_DIR 

fi 

 

echo -e "Dumping the server $HOST_NAME ...\c" 

for PID in $DUMP_PIDS ; do 

    $JAVA_HOME/bin/jstack $PID > $DUMP_DIR/jstack-$PID.dump 2>&1 

    echo -e ".\c" 

    $JAVA_HOME/bin/jinfo $PID > $DUMP_DIR/jinfo-$PID.dump 2>&1 

    echo -e ".\c" 

    $JAVA_HOME/bin/jstat -gcutil $PID > $DUMP_DIR/jstat-gcutil-$PID.dump 2>&1 

    echo -e ".\c" 

    $JAVA_HOME/bin/jstat -gccapacity $PID > $DUMP_DIR/jstat-gccapacity-$PID.dump 2>&1 

    echo -e ".\c" 

    $JAVA_HOME/bin/jmap $PID > $DUMP_DIR/jmap-$PID.dump 2>&1 

    echo -e ".\c" 

    $JAVA_HOME/bin/jmap -heap $PID > $DUMP_DIR/jmap-heap-$PID.dump 2>&1 

    echo -e ".\c" 

    $JAVA_HOME/bin/jmap -histo $PID > $DUMP_DIR/jmap-histo-$PID.dump 2>&1 

    echo -e ".\c" 

    if [ -r /usr/sbin/lsof ]; then 

    /usr/sbin/lsof -p $PID > $DUMP_DIR/lsof-$PID.dump 

    echo -e ".\c" 

    fi 

done 

if [ -r /usr/bin/sar ]; then 

/usr/bin/sar > $DUMP_DIR/sar.dump 

echo -e ".\c" 

fi 

if [ -r /usr/bin/uptime ]; then 

/usr/bin/uptime > $DUMP_DIR/uptime.dump 

echo -e ".\c" 

fi 

if [ -r /usr/bin/free ]; then 

/usr/bin/free -t > $DUMP_DIR/free.dump 

echo -e ".\c" 

fi 

if [ -r /usr/bin/vmstat ]; then 

/usr/bin/vmstat > $DUMP_DIR/vmstat.dump 

echo -e ".\c" 

fi 

if [ -r /usr/bin/mpstat ]; then 

/usr/bin/mpstat > $DUMP_DIR/mpstat.dump 

echo -e ".\c" 

fi 

if [ -r /usr/bin/iostat ]; then 

/usr/bin/iostat > $DUMP_DIR/iostat.dump 

echo -e ".\c" 

fi 

if [ -r /bin/netstat ]; then 

/bin/netstat > $DUMP_DIR/netstat.dump 

echo -e ".\c" 

fi 

echo "OK!"

你可能感兴趣的:(jvm)