行性能监控和故障处理指令
- 操作系统工具
- top:显示系统整体资源使用情况
- vmstat:监控内存和CPU
- iostat:监控IO使用
- netstat:监控网络使用
- JDK性能监控工具
- jps:虚拟机进程查看
- jstat:虚拟机运行时信息查看
- jinfo:虚拟机配置查看
- jmap:内存映像(导出)
- jhat:堆转储快照分析
- jstack:Java堆栈跟踪
- jcmd:实现上面除了jstat外所有命令的功能
可视化的性能监控和故障处理工具
JDK自带的性能监控工具
JConsole
VisualVM等
还有一些第三方的工具
MAT
JProfiler 等
常见参数配置
堆配置:
- -Xms:初始堆大小
- -Xms:最大堆大小
- -XX:NewSize=n:设置年轻代大小
- -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3表示年轻代和年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
- -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如3表示Eden: 3 Survivor:2,一个Survivor区占整个年轻代的1/5
- -XX:MaxPermSize=n:设置持久代大小
收集器设置:
- -XX:+UseSerialGC:设置串行收集器
- -XX:+UseParallelGC:设置并行收集器
- -XX:+UseConcMarkSweepGC:设置并发收集器
- -XX:+UseParalledlOldGC:设置并行年老代收集器
并行收集器设置
- -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数
- -XX:MaxGCPauseMillis=n:设置并行收集最大的暂停时间(如果到这个时间了,垃圾回收器依然没有回收完,也会停止回收)
- -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为:1/(1+n)
- -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况
- -XX:ParallelGCThreads=n:设置并发收集器年轻代手机方式为并行收集时,使用的CPU数。并行收集线程数
打印GC回收的过程日志信息
- -XX:+PrintGC
- -XX:+PrintGCDetails
- -XX:+PrintGCTimeStamps
- -Xloggc:filename
JVM调优思路
- 判断是否需要调优
如果各项参数设置合理,系统没有超时日志出现,GC 频率不高,GC 耗时不高,那么没有必要进行 GC 优化,如果 GC 时间超过 1-3 秒,或者频繁 GC,则必须优化
- 常规调优步骤
第一步:分析系统运行情况
a、实时监控
可以通过LINUX指令或者JDK指令查看程序运行情况(例如:查看那个进程占用cup比较高)
b、事后分析
所谓事后分析,指已经出现问题,通过GC日志分析(GCEasy等来分析GC情况,了解GC的频率、时间、内存占用等情况)或者堆存储快照分析
第二步:确定jvm调优量化目标
根据分析系统运行情况,明确内存使用率,停顿时间,回收频率等
第三步:确定调优参数
通过压测,调优内存,延迟等指标,对比调优前后差异。重复多次以上步骤。找到合适的参数
CPU飙高的排查思路
cpu飙高原因分析:肯定是存在程序长期占用CPU资源不释放。
- 排查步骤
1、所以先需要找出那个进程占用CPU高。
top 列出系统各个进程的资源占用情况。
2、然后根据找到对应进行里哪个线程占用CPU高。
top -Hp 进程ID 列出对应进程里面的线程占用资源情况
3、找到对应线程ID后,再打印出对应线程的堆栈信息
jstack PID 打印出进程的所有线程信息,从打印出来的线程信息中找到上一步转换为16进制的线程ID对应的线程信息。
4、最后根据线程的堆栈信息定位到具体业务方法,从代码逻辑中找到问题所在。
查看是否有线程长时间的watting 或blocked,如果线程长期处于watting状态下, 关注watting on xxxxxx,说明线程在等待这把锁,然后根据锁的地址找到持有锁的线程。
内存飙高排查思路
分析: 内存飚高如果是发生在java进程上,一般是因为创建了大量对象所导致,持续飚高说明垃圾回收跟不上对象创建的速度,或者内存泄露导致对象无法回收。
1、先观察垃圾回收的情况
- jstat -gc PID 1000 查看GC次数,时间等信息,每隔一秒打印一次。
- jmap -histo PID | head -20 查看堆内存占用空间最大的前20个对象类型,可初步查看是哪个对象占用了内存。
如果每次GC次数频繁,而且每次回收的内存空间也正常,那说明是因为对象创建速度快导致内存一直占用很高;如果每次回收的内存非常少,那么很可能是因为内存泄露导致内存一直无法被回收。
2、导出堆内存文件快照
- jmap -dump:live,format=b,file=/home/myheapdump.hprof PID dump堆内存信息到文件。
3、使用visualVM对dump文件进行离线分析,找到占用内存高的对象,再找到创建该对象的业务代码位置,从代码和业务场景中定位具体问题。
判断是否内存泄露
在jstat命令行工具中可以根据如下的思路来判断是否可能出现了内存泄露,具体思路如下:
-
运行中的Java程序,运行jstat命令行工具获取JVM运行的数据,重点关注OU值的数据(OU:老年代目前已使用空间)
-
重复如上的操作,如果OU的值呈上升的趋势,说明Java程序的老年代内存已使用量在不断上涨,那么也就意味着无法回收的对象在不断的增加,很有可能存在内存泄露。