JVM监控 | 8lovelife's life
0%

JVM监控

记录下如何监控JVM,包括JVM的线程、堆内存、CPU使用情况等

GC LOG

GC日志能够反应JVM内存的动态分配回收状况、应用停顿的时间,是GC调优的依据

JVM配置查询

jmap -heap [pid]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Mac:dmz-inward- mac$ jmap -heap 1016 (JDK1.8)
Attaching to process ID 1016, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.40-b25

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 22020096 (21.0MB)
MaxNewSize = 357564416 (341.0MB)
OldSize = 45088768 (43.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
capacity = 16777216 (16.0MB)
used = 11951560 (11.397895812988281MB)
free = 4825656 (4.602104187011719MB)
71.23684883117676% used
From Space:
capacity = 3145728 (3.0MB)
used = 2879968 (2.746551513671875MB)
free = 265760 (0.253448486328125MB)
91.55171712239583% used
To Space:
capacity = 3145728 (3.0MB)
used = 0 (0.0MB)
free = 3145728 (3.0MB)
0.0% used
PS Old Generation
capacity = 45088768 (43.0MB)
used = 857520 (0.8177947998046875MB)
free = 44231248 (42.18220520019531MB)
1.9018483716388082% used

4674 interned Strings occupying 366808 bytes.

GC日志文件

  • -verbose:gc
  • -XX:+PrintGCDetails
  • -XX:+PrintGCApplicationStoppedTime
  • -XX:+PrintGCDateStamps
  • -XX:+PrintHeapAtGC , GC前后输出堆内存大小
  • -Xloggc:[file] , GC信息输出到独立文件中
  • -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=[file] ,记录 堆内存耗尽时的堆快照
  • -XX:ErrorFile=[file] ,记录JVM虚拟机本身的异常信息
1
-XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+PrintHeapAtGC -Xloggc:/tmp/gc.log  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/ -XX:ErrorFile=/tmp/JVM_Error.log

jstat

  1. GC、堆内存信息总情况

jstat -gcutil [pid] [intervel] [count]

1
2
3
4
5
6
7
8
9
10
Mac:JDK mac$ jstat -gcutil 3157 500 2
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 52.00 97.79 66.51 69.76 3 0.022 2 0.067 0.089
0.00 0.00 52.00 95.80 66.51 69.76 3 0.022 2 0.067 0.089

S0 S1 E O M : 表示堆内存各区已使用空间的百分比
YGC FGC : 表示Young GC、Full GC 的次数
YGCT FGCT GCT : 表示YoungGC、Full GC 、GC 所用的时间
CCS : 压缩使用比例

  1. 年轻代GC情况

    jstat -gcnew [pid] [intervel] [count]

1
2
3
4
5
6
7
8
9
10
11
Mac:JDK mac$ jstat -gcnew 3157 500 2
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
512.0 512.0 0.0 0.0 7 15 512.0 2048.0 1065.0 11 0.044
512.0 512.0 0.0 0.0 7 15 512.0 2048.0 1065.0 11 0.044

S0C S1C EC : S0、S1、E区大小(KB)
S0U S1U EU : S0、S1、E区已使用大小(KB)
TT : 对象在新生代存活的次数
MTT : 对象的最大年龄
DSS : 期待的Survivor区大小

  1. 年轻代内存统计

    jstat -gcnewcapacity [pid]

1
2
3
4
5
6
7
Mac:JDK mac$ jstat -gcnewcapacity 3157
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
3072.0 13312.0 3072.0 4096.0 512.0 4096.0 512.0 12288.0 2048.0 15 14

NGCMN NGCMX : 年轻代最小、最大空间
NGC :当前年轻代大小

  1. 年老代

    jstat -gcold [pid] [intervel] [count]

    jstat -gcoldcapacity [pid]

  2. 元数据空间

    jstat -gcmetacapacity [pid]

1
2
3
4
5
6
7
Mac:JDK mac$ jstat -gcmetacapacity 3157
MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT
0.0 1056768.0 4864.0 0.0 1048576.0 512.0 17 16 0.491 0.556

CCSMN CCSMX : 压缩类最小、最大空间
CCSC : 当前压缩类空间大小

命令行监控

命令行监控可结合脚本共同使用

jcmd

1
2
3
4
5
获取运行的JVM进程:jcmd -l
获取JVM运行的时间:jcmd process_id VM.uptime
获取系统属性:jcmd process_id VM.system_properties
获取JVM调优参数:jcmd process_id VM.flags
获取JVM线程信息:jcmd process_id Thread.print

堆快照文件

jmap用于导出堆的快照文件,便于后续分析

1
2
3
4
Mac:JDK mac$ jmap -dump:format=b,file=/Users/mac/IdeaProjects/JDK/heap.hprof 3157
Dumping heap to /Users/mac/IdeaProjects/JDK/heap.hprof ...
Heap dump file created

线程栈文件

将线程栈信息导入文件
jstack [pid] > threaddump.out | jcmd [pid] Thread.print > ./threaddump.out

1
2
Mac:JDK mac$ jcmd 3157 Thread.print > ./threaddump.out

图形化监控

JDK内置有jvisualvm 、jconsole 直观的图形化监控工具

VisualVM

1
2
3
通过命令行直接唤醒启动

Mac:JDK mac$ jvisualvm

image

Visual GC

Visual GC提供图形化的JVM堆内存使用的动态监控,由VisualVM以插件的形式提供

image

  • 堆内存动态监控

image

A magician is a man of his word. - Alfred Borden

The Prestige

事例

如何定位服务器 CPU 使用率过高的问题?可以通过如下几个步骤

获取系统进程信息

1
2
# 每隔 5s 刷新一次
top -c -d5

找出 CPU 使用率最高的 PID

image

获取指定进程的线程信息

1
top -H -p 1

image

找出 CPU 使用率最高的 PID(这里是线程 ID),并将线程 ID 转换为16进制值

1
2
printf '0x%x\n' 6
# 0x6

查询线程信息,并定位源码位置

1
jstack 1 | grep 0x6 -A 50

image