Java程序运行状态的监控
写在前面:
该系列文章,主要是为了深入学习Java完成的一条链,推荐阅读的整体顺序为:Java的内存模型(根源),一个java文件被执行的历程,一个Java类的加载,Java的垃圾回收机制及算法,Linux(六):系统运维常用命令 和 Java程序运行状态的监控(实用,定位Java程序问题)
JVM的内存模型
在进行GC的时候,不考虑方法区和栈区的部分,因为在java中,垃圾回收主要是针对对象,也就是堆区内存,如上图,堆内存在实际中是分层的;实质上是分为三大块,即新生代(YoungGen)、老年代(Old Memory)、永久区(Perm),新生代又细分为伊甸区(Eden)、生还区(S0、S1),其中伊甸区主要是存放刚诞生的对象(即代码中新new出的对象),S1,S2主要存放新生代经过垃圾清理后存活的对象;
注:这里用的是老图,永久区(Perm)在Java8已经被取缔了
垃圾回收的过程
垃圾回收即GC,主要分为两种,一种为Minor GC,也叫YGC,是最频繁的GC,发生在新生代,Java应用在运行过程中会大量的创建对象,这些对象可能用完即销毁,所以基本在新生代就被回收了。另一种称为Major GC,主要发生在老年代;还有一个含糊不定的概念,即FullGC,大众理解的话,当老年代也满了,则会对整个堆内存进行全量的回收。但是实际情况中,我们主要看的是gc.log日志,其中也会发现在部分gc日志头中也有Full GC字眼,此处表示含义是在这次GC的全过程中,都是STW的状态,也就是说在这次GC的全过程中所有用户线程都是处于暂停的状态。
STW状态:
stop the world指的是用户线程在运行至安全点(safe point)或安全区域(safe region)之后,就自行挂起,进入暂停状态,对外的表现看起来就像是全世界都停止运转了一样,而不论何种gc算法,不论是minor gc还是major gc都会stop the world,区别只在于stop the world的时间长短。
当发生YGC,新生代中没有被任何其他对象所引用的对象将会从内存中被清除,还被其他对象引用的则放到幸存者区。当发生多次YGC,在S0、S1区多次没有被清楚的对象,则会被移到老年代区域。当老年代区域被占满的时候,则会发送Major GC。
监控命令
jps命令:虚拟机进程状况
查看所有的jvm进程,包括进程ID,进程启动的路径等等。
命令格式:
jps [option]
参数选项:
选项 | 作用 |
-q | 只输出LVMID,省略主类的名称 |
-m | 输出虚拟机进程启动时传递给主类main()函数的参数 |
-l | 输出主类的全名,如果进程执行的是jar包,则输出jar路径 |
-v | 输出虚拟机进程启动时的JVM参数 |
jstat命令:虚拟机统计信息监视工具
jstat(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程[1]虚拟机进程中的类加载、内存、垃圾收集、即时编译等运行时数据,在没有GUI图形界面、只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的常用工具。
命令格式:
jstat [ option vmid [interval[s|ms] [count]] ]
参数option为命令选项,vmid则是通过jps获取到的jvm运行号,参数interval和count代表查询间隔和次数,如果省略这2个参数,说明只查询一次。如果每秒进行10次监听,则命令为 jstat -XX vmid 1000 10
参数选项:
参数 | 作用 |
-class | 监视类加载、卸载数量,总空间以及类装载所耗费的时间 |
-gc | 监视java堆状况,包括Eden区、2个survival区、老年代,永久代等的容量,已用空间,垃圾收集时间合计等信息。 |
-gccapacity | 监视内容与-gc基本相同,但输出主要关注java堆各个区域所用到的最大、最小空间。 |
-gcutil | 监视内容与-gc基本相同,单输出主要关注已用空间占总空间的百分比。 |
-gccause | 与-gcutil功能一样,但是会额外输出导致上一次垃圾收集产生的原因。 |
-gcnew | 监视新生代垃圾收集状况 |
-gcnewcapacity | 监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间。 |
-gcold | 监视老年代垃圾收集状况。 |
-gcoldcapacity | 监视内容与-gcold基本线头,输出主要关注使用的最大、最小空间。 |
-gcpermcapacity | 输出永久代用到的最大、最小空间。 |
-compiler | 输出即时编译器编译过的方法、耗时等信息。 |
-printtcompilation | 输出已经被即时编译的方法。 |
以上实际使用过程中,并不会全部用到,较为常用的主要为-class、-gc、-gcutil;
执行样例:
-class
返回解释:
#Loaded 类加载数量
#Bytes 加载的大小(k)
#Unloaded 类卸载的数量
#Bytes 卸载的大小(k)
#Time 时间花费在执行类加载和卸载操作
-gc
-gcutil
返回解释:
#S0C 生还者区0 容量(KB)
#S1C 生还者区1 容量(KB)
#S0U 生还者区0 使用量(KB)
#S1U 生还者区1 使用量(KB)
#EC 伊甸园区容量(KB)
#EU 伊甸园区使用量(KB)
#OC 老年区容量(KB)
#OU 老年区使用量(KB)
#PC 永久区容量(KB)
#PU 永久区使用量(KB)
#YGC 新生代GC次数
#YGCT 新生代GC时间
#FGC full GC 事件的次数
#FGCT full GC的时间
#GCT 总GC时间
jinfo:Java配置信息工具
jinfo(Configuration Info for Java)的作用是实时查看和调整虚拟机各项参数。使用jps命令的-v参数可以查看虚拟机启动时显式指定的参数列表。
jstack:Java堆栈跟踪工具
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过jstack来查看各个线程的调用堆栈,就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
命令格式:
jstack [ option ] vmid
参数选项:
参数 | 作用 |
-L | 除堆栈外,显示关于锁的附加信息。 |
-F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
执行样例: