常用命令:
jstat -gcutil <pid> 1000
gc垃圾回收信息
gcXXX各区域GC的详细信息,如-gcold
Java 堆分为新生代和老年代,新生代一般划分为三块区域,Eden + From Survivor + To Survivor,Eden 和 Survivor 的内存比为8:1,每次只使用一个Eden 和一个 Survivor 区域,另一个 Survivor 用于复制收集算法回收内存。
对象一般尽量分配到新生代中,而对于大对象(长字符串和大数组)直接分配在老年代中,同时“年龄”长的的对象会从新生代自动晋升到老年代中。
当 Eden 区域分配不足时,自动发生一次 Minor GC。
当发生 Minor GC 时,虚拟机会自动检测(比较)新生代晋升到老年代的对象内存大小和老年代剩余内存大小,如果晋升>剩余,则发生一次Full GC;如果晋升
YGC: 从应用程序启动到当前,发生Yang GC 的次数
YGCT: 从应用程序启动到当前,Yang GC所用的时间【单位秒】
FGC: 从应用程序启动到当前,发生Full GC的次数
FGCT: 从应用程序启动到当前,Full GC所用的时间
GCT: 从应用程序启动到当前,用于垃圾回收的总时间【单位秒】
1) 从应用程序启动到当前;
2) 触发YGC的条件;
3) 触发FGC的条件;
4) 垃圾回收的时间,单位是秒;
5) Eden区域满了以后才会触发一次YGC。
出现cpu突然飙升的可能原因
1)死循环,或者大量for循环;
2)大量的gc正在被触发;(例如:每秒执行一次gc)
一直在触发FULL GC的可能原因
年轻代到年老代的晋升不断被触发,年轻代空间不够用。
应用服务器(java)莫名其妙的出现被kill掉现象。应用进程被杀掉。
可能的原因:Java应用程序的问题:发生OOM导致进程Crash
一般情况下,出现OOM异常,JVM的GC会进行回收,是不会直接导致JVM进程退出的。如果出现退出的情况,那就是内存泄漏,由于内存占用越来越大,结果操作系统杀掉进程。
现象:出现CPU飙升的情况,要么走到了死循环,要么就是在做大量的GC。使用jstat -gc pid [interval]命令查看了java进程的GC状态,果然,FULL GC达到了每秒一次。
这么多的FULL GC,应该是内存泄漏没跑了,于是使用jstack pid > jstack.log保存了线程栈的现场。
一直在触发FULL GC,说明了什么问题?年轻代没内存了,为什年轻代没内存了?
线上应用宕机。紧急排查发现应用的的进程已经不在了,怀疑是因为内存占用过多导致被操作系统杀进程了。接着查看操作系统日志,如下,果然发现是因为内存占用高达8G而被系统直接杀进程。
CPU满载
应用重启后,刚开始几分钟很正常,但是很快监控报警CPU占用过高,并且应用很快不再响应外部的任何请求,所有的HTTP请求全部阻塞直到网关超时。
通过top命令立即定位到CPU占用高的进程正是刚刚重启的应用。然后通过命令,来定位java应用是那个线程占用CPU过高.
CPU占用高的并不是用户线程,而是JVM的线程,怀疑是不是GC出了问题。
如何区分用户线程还是jvm线程?