一、jps【查看进程id】

  当我们启动了一个web应用程序时,可以通过jps查看其进程id,接着用各种jdk自带命令优化应用。

  使用方式:

java vm 线程查看 jvm查看线程状态命令_老年代

二、jmap【查看内存信息,实例个数以及占用内存大小】

查看内存信息

java vm 线程查看 jvm查看线程状态命令_JVM_02

java vm 线程查看 jvm查看线程状态命令_java vm 线程查看_03

  • num:序号
  • instances :实例数量
  • bytes :占用空间大小
  • class name :类名称
  • [C :char[]
  • [S :short[]
  • [I:int[]
  • [B:byte[]
  • [[I:int[][]

查看堆信息

java vm 线程查看 jvm查看线程状态命令_JVM_04

java vm 线程查看 jvm查看线程状态命令_java vm 线程查看_05

JVM生成的dump文件分析

  我们可以在应用程序执行时设置VM参数,让其生成dump文件,用来分析应用的内存使用情况:

java vm 线程查看 jvm查看线程状态命令_垃圾回收_06

java vm 线程查看 jvm查看线程状态命令_垃圾回收_07

java vm 线程查看 jvm查看线程状态命令_java vm 线程查看_08

java vm 线程查看 jvm查看线程状态命令_java vm 线程查看_09

java vm 线程查看 jvm查看线程状态命令_java vm 线程查看_10

java vm 线程查看 jvm查看线程状态命令_java vm 线程查看_11

三、jstack【查看栈信息,CPU占用情况】

查看栈线程信息

java vm 线程查看 jvm查看线程状态命令_JVM_12

 

java vm 线程查看 jvm查看线程状态命令_老年代_13

java vm 线程查看 jvm查看线程状态命令_JVM_14

  • Thread-1线程名
  • prio=5优先级=5
  • os_prio=0操作系统执行的优先级
  • tid=0x000000001fa9e000java的线程id
  • nid=0x2d64线程对应的CPU线程标识nid
  • java.lang.Thread.StateBLOCKED 线程状态

java vm 线程查看 jvm查看线程状态命令_JVM_15

java vm 线程查看 jvm查看线程状态命令_垃圾回收_16

java vm 线程查看 jvm查看线程状态命令_垃圾回收_17

四、Jinfo【查看Java系统参数和JVM参数】

查看jvm的参数

java vm 线程查看 jvm查看线程状态命令_java vm 线程查看_18

查看java系统参数

java vm 线程查看 jvm查看线程状态命令_老年代_19

五、Jstat【查看堆内存各部分的使用量】

格式:jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]

垃圾回收统计

java vm 线程查看 jvm查看线程状态命令_垃圾回收_20

java vm 线程查看 jvm查看线程状态命令_老年代_21

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

新生代垃圾回收统计

java vm 线程查看 jvm查看线程状态命令_老年代_22

  • S0C :第一个幸存区的大小,单位KB
  • S1C :第二个幸存区的大小
  • S0U :第一个幸存区的使用大小
  • S1U :第二个幸存区的使用大小
  • TT :对象在新生代存活的次数
  • MTT :对象在新生代存活的最大次数
  • DSS :期望的幸存区大小
  • EC :伊甸园区的大小
  • EU :伊甸园区的使用大小
  • YGC :年轻代垃圾回收次数
  • YGCT :年轻代垃圾回收消耗时间

老年代垃圾回收统计

java vm 线程查看 jvm查看线程状态命令_老年代_23

  • MC :方法区大小,单位KB
  • MU:方法区使用大小
  • CCSC :压缩类空间大小
  • CCSU :压缩类空间使用大小
  • OC :老年代大小
  • OU :老年代使用大小
  • YGC :年轻代垃圾回收次数
  • FGC :老年代垃圾回收次数
  • FGCT :老年代垃圾回收消耗时间
  • GCT :垃圾回收消耗总时间

堆内存统计

java vm 线程查看 jvm查看线程状态命令_JVM_24

  • NGCMN :新生代最小容量,单位KB
  • NGCMX :新生代最大容量
  • NGC :当前新生代容量
  • S0C :第一个幸存区大小
  • S1C :第二个幸存区的大小
  • EC :伊甸园区的大小
  • OGCMN :老年代最小容量
  • OGCMX :老年代最大容量
  • OGC :当前老年代大小
  • OC :当前老年代大小
  • MCMN :最小元数据容量
  • MCMX :最大元数据容量
  • MC :当前元数据空间大小
  • CCSMN :最小压缩类空间大小
  • CCSMX :最大压缩类空间大小
  • CCSC :当前压缩类空间大小
  • YGC :年轻代gc次数
  • FGC :老年代GC次数

新生代内存统计

java vm 线程查看 jvm查看线程状态命令_垃圾回收_25

  • NGCMN
  • NGCMX
  • NGC
  • S0CMX
  • S0C
  • S1CMX
  • S1C
  • ECMX
  • EC
  • YGC
  • FGC

老年代内存统计

java vm 线程查看 jvm查看线程状态命令_java vm 线程查看_26

  • OGCMN
  • OGCMX
  • OGC
  • OC
  • YGC
  • FGC
  • FGCT
  • GCT

六、优化思路

jstat gc -pid

  优化思路:尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留存在年轻代里,尽量别让对象进入老年代。尽量减少Full GC的频率,避免频繁Full GC对JVM性能的影响。

年轻代对象增长的速率

  可以执行命令 jstat -gc pid 1000 10 (每隔1秒执行1次命令,共执行10次),通过观察EU(eden区的使用)来估算每秒eden大概新增多少对象,如果系统负载不高,可以把频率1秒换成1分钟,甚至10分钟来观察整体情况。

  PS:一般系统可能有高峰期和日常期,所以需要在不同的时间分别估算不同情况下对象增长速率。

Young GC的触发频率和每次耗时

  知道年轻代对象增长速率我们就能推根据eden区的大小推算出Young GC大概多久触发一次,Young GC的平均耗时可以通过 YGCT/YGC 公式算出,根据结果我们大概就能知道系统大概多久会因为Young GC的执行而卡顿多久。

每次Young GC后有多少对象存活和进入老年代

  根据上一步的分析已经大概知道Young GC的频率,假设是每5分钟一次,那么可以执行命令 jstat -gc pid 300000 10 ,观察每次结果eden, survivor和老年代使用的变化情况,在每次gc后eden区使用一般会大幅减少,survivor和老年代都有可能增长,这些增长的对象就是每次Young GC后存活的对象,同时还可以看出每次Young GC后进去老年代大概多少对象,从而可以推算出老年代对象增长速率。

Full GC的触发频率和每次耗时

  知道了老年代对象的增长速率就可以推算出Full GC的触发频率了,Full GC的每次耗时可以用公式 FGCT/FGC 计算得出。

七、小问答

Q:突然内存飙升怎么办?

  首先用JVM调优工具看看是不是有大量的类生成了,或者是不是有死循环在暂用资源,还可以用jstack命令来监视,找出占用CPU最高的线程堆栈信息。

Q:如何防止代码中的主动gc影响性能呢?

-XX:DisableExplicitGC参数来使得代码内的System.gc()【会造成多余的full gc】这种代码不生效。