Java GC 监测

English Orignal Link: http://www.journaldev.com/2856/java-jvm-memory-model-and-garbage-collection-monitoring-tuning

我们可以通过命令行或者UI工具监测应用的内存使用情况. 这里我们用Java2Demo.jar作为测试应用.
jstat
然后我们在Java2Demo.jar所在的目录打开一个命令行窗口, 命令行里启动这个程序:
java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar
启动后, 保持程序不要最小化.

我们需要知道正在运行的程序的端口号.
ps -eaf | grep Java2Demo.jar
然后就可以看到
bejond 5002 4977 7 11:20 pts/3 00:11:01 java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar bejond 10751 6230 0 13:52 pts/24 00:00:00 grep --color=auto Java2Demo.jar
端口是5002.

可以用jstat命令来观察JVM和内存使用情况:
jstat -gc 5502 2000
这个命令是用来查看5002号端口的GC情况, 没2000毫秒刷新一次. 显示的结果类似如下:

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
49
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU        YGC    YGCT   FGC       FGCT      GCT   
1024.0 1024.0 0.0 1.0 8192.0 4445.9 20480.0 10087.2 20480.0 16769.8 93 0.092 45 1.360 1.452
1024.0 1024.0 0.0 1.0 8192.0 6749.7 20480.0 10087.2 20480.0 16769.8 93 0.092 45 1.360 1.452
1024.0 1024.0 1.0 0.0 8192.0 1160.5 20480.0 10087.2 20480.0 16769.8 94 0.093 45 1.360 1.453
1024.0 1024.0 1.0 0.0 8192.0 3475.4 20480.0 10087.2 20480.0 16769.8 94 0.093 45 1.360 1.453
1024.0 1024.0 1.0 0.0 8192.0 5937.9 20480.0 10087.2 20480.0 16769.8 94 0.093 45 1.360 1.453
1024.0 1024.0 1.0 0.0 8192.0 8192.0 20480.0 10087.2 20480.0 16769.8 94 0.093 45 1.360 1.453
1024.0 1024.0 0.0 1.8 8192.0 2474.5 20480.0 10087.2 20480.0 16769.8 95 0.094 45 1.360 1.454
1024.0 1024.0 0.0 1.8 8192.0 4775.0 20480.0 10087.2 20480.0 16769.8 95 0.094 45 1.360 1.454
1024.0 1024.0 0.0 1.8 8192.0 7242.4 20480.0 10087.2 20480.0 16769.8 95 0.094 45 1.360 1.454
1024.0 1024.0 1.0 0.0 8192.0 1490.7 20480.0 10087.3 20480.0 16769.8 96 0.095 45 1.360 1.455
1024.0 1024.0 1.0 0.0 8192.0 3794.8 20480.0 10087.3 20480.0 16769.8 96 0.095 45 1.360 1.455
1024.0 1024.0 1.0 0.0 8192.0 6262.4 20480.0 10087.3 20480.0 16769.8 96 0.095 45 1.360 1.455
1024.0 1024.0 0.0 0.9 8192.0 494.5 20480.0 10087.3 20480.0 16769.8 97 0.095 45 1.360 1.455
1024.0 1024.0 0.0 0.9 8192.0 2796.8 20480.0 10087.3 20480.0 16769.8 97 0.095 45 1.360 1.455
1024.0 1024.0 0.0 0.9 8192.0 5100.1 20480.0 10087.3 20480.0 16769.8 97 0.095 45 1.360 1.455
1024.0 1024.0 0.0 0.9 8192.0 7565.3 20480.0 10087.3 20480.0 16769.8 97 0.095 45 1.360 1.455
1024.0 1024.0 1.1 0.0 8192.0 1809.8 20480.0 10087.3 20480.0 16769.8 98 0.096 45 1.360 1.456
1024.0 1024.0 1.1 0.0 8192.0 4110.9 20480.0 10087.3 20480.0 16769.8 98 0.096 45 1.360 1.456
1024.0 1024.0 1.1 0.0 8192.0 6415.6 20480.0 10087.3 20480.0 16769.8 98 0.096 45 1.360 1.456
1024.0 1024.0 0.0 1.6 8192.0 662.7 20480.0 10087.3 20480.0 16769.8 99 0.096 45 1.360 1.456
1024.0 1024.0 0.0 1.6 8192.0 3129.2 20480.0 10087.3 20480.0 16769.8 99 0.096 45 1.360 1.456
1024.0 1024.0 0.0 1.6 8192.0 5431.5 20480.0 10087.3 20480.0 16769.8 99 0.096 45 1.360 1.456
1024.0 1024.0 0.0 1.6 8192.0 7733.7 20480.0 10087.3 20480.0 16769.8 99 0.096 45 1.360 1.456
1024.0 1024.0 1.0 0.0 8192.0 1984.4 20480.0 10087.3 20480.0 16769.8 100 0.097 45 1.360 1.457
1024.0 1024.0 1.0 0.0 8192.0 4448.6 20480.0 10087.3 20480.0 16769.8 100 0.097 45 1.360 1.457
1024.0 1024.0 1.0 0.0 8192.0 6753.0 20480.0 10087.3 20480.0 16769.8 100 0.097 45 1.360 1.457
1024.0 1024.0 0.0 1.0 8192.0 994.0 20480.0 10087.3 20480.0 16769.8 101 0.097 45 1.360 1.457
1024.0 1024.0 0.0 1.0 8192.0 3463.0 20480.0 10087.3 20480.0 16769.8 101 0.097 45 1.360 1.457
1024.0 1024.0 0.0 1.0 8192.0 5766.2 20480.0 10087.3 20480.0 16769.8 101 0.097 45 1.360 1.457
1024.0 1024.0 0.9 0.0 8192.0 0.0 20480.0 10087.3 20480.0 16769.8 102 0.099 45 1.360 1.459
1024.0 1024.0 0.9 0.0 8192.0 2464.8 20480.0 10087.3 20480.0 16769.8 102 0.099 45 1.360 1.459
1024.0 1024.0 0.9 0.0 8192.0 4768.3 20480.0 10087.3 20480.0 16769.8 102 0.099 45 1.360 1.459
1024.0 1024.0 0.9 0.0 8192.0 7231.0 20480.0 10087.3 20480.0 16769.8 102 0.099 45 1.360 1.459
1024.0 1024.0 0.0 7.2 8192.0 1317.7 20480.0 10087.3 20480.0 16769.8 103 0.099 45 1.360 1.459
1024.0 1024.0 0.0 7.2 8192.0 3785.2 20480.0 10087.3 20480.0 16769.8 103 0.099 45 1.360 1.459
1024.0 1024.0 0.0 7.2 8192.0 6086.6 20480.0 10087.3 20480.0 16769.8 103 0.099 45 1.360 1.459
1024.0 1024.0 1.0 0.0 8192.0 336.4 20480.0 10087.3 20480.0 16769.8 104 0.100 45 1.360 1.460
1024.0 1024.0 1.0 0.0 8192.0 2802.0 20480.0 10087.3 20480.0 16769.8 104 0.100 45 1.360 1.460
1024.0 1024.0 1.0 0.0 8192.0 5105.4 20480.0 10087.3 20480.0 16769.8 104 0.100 45 1.360 1.460
1024.0 1024.0 1.0 0.0 8192.0 7567.9 20480.0 10087.3 20480.0 16769.8 104 0.100 45 1.360 1.460
1024.0 1024.0 0.0 1.6 8192.0 1811.9 20480.0 10087.3 20480.0 16769.8 105 0.101 45 1.360 1.461
1024.0 1024.0 0.0 1.6 8192.0 4111.1 20480.0 10087.3 20480.0 16769.8 105 0.101 45 1.360 1.461
1024.0 1024.0 0.0 1.6 8192.0 6573.7 20480.0 10087.3 20480.0 16769.8 105 0.101 45 1.360 1.461
1024.0 1024.0 1.0 0.0 8192.0 828.8 20480.0 10087.3 20480.0 16769.8 106 0.101 45 1.360 1.461
1024.0 1024.0 1.0 0.0 8192.0 3133.0 20480.0 10087.3 20480.0 16769.8 106 0.101 45 1.360 1.461
1024.0 1024.0 1.0 0.0 8192.0 5597.5 20480.0 10087.3 20480.0 16769.8 106 0.101 45 1.360 1.461
1024.0 1024.0 1.0 0.0 8192.0 7898.7 20480.0 10087.3 20480.0 16769.8 106 0.101 45 1.360 1.461
1024.0 1024.0 0.0 1.0 8192.0 2305.3 20480.0 10087.3 20480.0 16769.8 107 0.102 45 1.360 1.462

上面的是我运行Java2Demo.jar很久后的到的结果.

  • S0C和S1C: Survivor0和Survivor1区的大小(C就是count, 我猜的)
  • S0U和S1U: S0和S1被使用的空间, 可以看到总有一个空间是0, 这是每次执行Minor GC后压缩的结果.(U就是used, 也是我猜的)
  • EC和EU: Eden Count, Eden Used, 即Eden的大小和Eden被使用了多少. 可以看到Eden是S0的8倍. 可以看到EU慢慢增长, 当达到EC时会触发Minor GC而变小. 这时候S0U和S1U都会变化. OU也会变大.
  • OC和OU: Old Gen Count, Old Gen Used, 即Old Gen的大小和Old Gen被使用的情况.
  • PC和PU: Perm Gen Count, Perm Gen Used. 即Perm大小和Perm被使用的情况.
  • YGC和YGCT: Young GC, Young GC Time. 就是在Young Gen里执行了多少次Minor GC和每次执行所用的时间. 你会发现YGCT会越来越大, 也就意味着程序运行会越来越慢.
  • FGC和FGCT: Full GC, Full GC Time. 就是执行Full GC次数和Full GC所用的时间. 你会奇怪FGC怎么是47, 这是在启动Java2Demo时加载程序的资源, 所以会执行很多次Full GC. 这不必怀疑. 但是如果你的程序运行一段时间后频繁full GC那就一定有问题了.
  • GCT: GC time. 表示GC所用的时间, 是YGC+FGC.

jstat有一个优点是可以在远端的服务器启动这个监听.

Java VisualVM和Visual GC
jvisualvm是JDK自带的内存监听程序, 在命令行执行
jvisualvm
就会启动这个UI程序. 程序启动后, 在Tool -> Plugins -> Available Plugins, 找到Visual GC, 安装.
然后回到程序主页, 在左边导航栏里能看到Java2Demo{pid 5002}, 点击, 然后打开"Visual GC"页签, 就可以看到GC的信息了.

Java GC 调优
Java GC调优应该是在你优化程序后提高性能的方案. 另外, 如果GC花费时间太长, 可以考虑调优.
如果你看到java.lang.OutOfMemoryError: PermGen space错误, 可以试着将-XX:PermGen-XX:MaxPermGen调大. 也可以使用-XX:+CMSClassUnloadingEnabled来检查使用CMS GC时情况怎么样.
如果你看到很多Full GC操作, 可以试着提高Old Gen的大小. 但是注意, 不是说越大的内存空间就越好, 空间越大执行Major GC的时机就越晚, 而长时间不GC会导致JVM分配内存很慢, 应该是垃圾对象太多的缘故, 所以Old Gen太大反而会拖慢程序的速度. 只有熬到Old Gen满了, 执行Major GC后才会快. 而如果Old Gen很大, 迟迟不触发Major GC, 程序会越来越慢, 反而找不到问题.

GC调优需要有很多的努力, 很多的经验去实践, 才能得到最好的适应你的应用的性能结果.

Share