重要的监控数据
对于JVM的性能监控,主要注意以下一些参数,通过JVM自带的命令行工具,即可检测相关参数,从而找出系统或程序中存在的性能问题
- 当前使用的GC
- Java堆的大小,新生代和老年代的大小,永久代的大小
- Minor GC的频率和持续时间,Full GC的频率和持续时间
- 每个并发GC周期内的空间回收量
- GC前后JAVA堆的占用量
- GC前后新生代和老年代的占用量
- GC前后永久代的占用量
- 是否显示调用了System.gc()
命令行工具
几个比较有用的命令行工具,可以帮助我们只管的检测到JVM的相关参数
jps(JVM Process Status Tool) JVM进程状况工具:
- 主要功能:列出正在运行的虚拟机进程,并显示执行主类的名称及进程在本地JVM中的ID(LVMID), 与ps命令相似,可以查看JVM中的进程ID
- 使用方法:jps [options][hostid]
[options]:
-q: 只输出LVMID
-m: 输出JVM启动时传给主类的方法
-l:输出主类的全名,如果是Jar则输出jar的路径
-v: 输出JVM启动参数
jstat(JVM Statistics Monitoring Tool) JVM统计信息监控工具:
- 主要功能:监控JVM各种运行状态信息,如虚拟机进程中的类装载、内存、GC、JIT编译等数据
- 使用方法:jstat [options vmid [interval [s|ms] [count] ]]
- options:
- vmid:
- 本地JVM进程:与LVMID一直,使用jps查看
- 远程JVM进程:[protocol:][//]LVMID[@hostname[:post]/servername]
- internal和count:
- 代表查询间隔和次数,忽略说明只查询一次
- 实例:
jstat -gcutil 16270 250 10 //每250ms查询一次进程16270的GC情况,共20次
jmap(JVM Memory Map for Java) Java内存映像工具
- 主要功能:1.用于生成堆转储快照,即dump文件;2. 可以查询finalize执行队列、Java堆和永久代的详细信息(使用率、当前用的GC等)
- 使用方法:jmap [options] vmid
- options:
实例:
jmap -histo 16270 >a.log //16270进程堆栈中对象的统计信息
- instances:表示实例数量
- bytes:表示内存占用
- class name:表示类全名信息
* 注:jmap使用的时候JVM会处于假死状态,只能在服务瘫痪的时候为了解决问题来使用,否则会造成服务中中断*
jstack(JVM Stack Trace for Java) : 堆栈跟踪工具
- 功能:1. 用于生成JVM当前时刻的线程快照(即当前JVM内每一个条线程正在执行的方法堆栈集合);2.用于分析线程出现长时间停顿的原因
- 使用方法:jstack [options] vmid
- options:
- 实例:jstack -l 16270 //查看16270的线程快照
线程的状态:
- Runnable:该线程具备所有运行条件,在运行队列中准备操作系统的调度,或正在运行
- Wait on condition:线程等待某个条件的发生,如网络读写等。可通过stacktrace来分析
- Waiting for monitor entry:处于Entry Set监控器队列
- In Ojbect.wait():处于Wait Set监控器队列
线程锁住资源
- 死锁:通过dump信息可以查看是否线程间存在死锁
- 热锁:多个线程对临界区或者锁的竞争,往往是导致系统性能瓶颈的主要因素
实例:Eclipse性能调优
综合使用JVM命令行对Eclise性能调优
1.基本配置:
2.JVM现状:
3.使用eclipse可视化性能分析插件,观测到以下结果:
- 从JVM堆的监视曲线中得到:
- “堆大小”曲线和“使用堆”曲线一直都是很大的间隔距离
- “最大堆”曲线向上:JVM内部在进行堆扩容
- “使用堆”曲线向下:JVM出发了一次GC
- 永久代的监视曲线
- “PermGen大小”曲线和“使用PermGen”完全重合
- 说明:永久代中没有可回收的资源,所以“使用PermGen”曲线不会向下发展
得出的结论是:永久代导致的内存溢出
优化分析:
- 减少时间:
- 新生代:GC太频繁,太小
- 老年代:GC用时太长,不停地扩容
- 减少时间:
- 优化计划:
- 新生代提升到128M:避免新生代频繁GC
- 堆设置为512M,永久代设置为96M,并设置成固定值,以避免内存扩展