JVM相关总结

JVM参数具体参考:http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

1、GC监控

jstat -gc -t pid 1000 100
对pid进程进行每隔1000毫秒的采样,采样次数为100

2、java的进程号:jps

jps:即java process status

3、jstat

从最简单的jstat工具开始:我想很多人都是用过unix系统里的ps命令,这个命令主要是用来显示当前系统的进程情况,有哪些进程,及其id。 jps 也是一样,它的作用是显示当前系统的java进程情况,及其id号。我们可以通过它来查看我们到底启动了几个java进程(因为每一个java程序都会独 占一个java虚拟机实例),和他们的进程号(为下面几个程序做准备),并可通过opt来查看这些进程的详细启动参数。
使用方法:在当前命令行下打 jps(需要JAVA_HOME,没有的话,到改程序的目录下打)
接下来是jstat,我之所以这次调优是因为,目前情况下,并发用户一多就会产生 响应时间长的问题。虽然很开就解决了,决定首先对VM内存使用量监控。jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载 类的数量。使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意义。
语法结构:
Usage: jstat -help|-options
       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
 参数解释:
Options — 选项,我们一般使用 -gcutil 查看gc情况
vmid    — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为秒或者毫秒
count   — 打印次数,如果缺省则打印无数次
S0  — Heap上的 Survivor space 0 区已使用空间的百分比
S1  — Heap上的 Survivor space 1 区已使用空间的百分比
E   — Heap上的 Eden space 区已使用空间的百分比
O   — Heap上的 Old space 区已使用空间的百分比
P   — Perm space 区已使用空间的百分比
YGC — 从应用程序启动到采样时发生 Young GC 的次数
YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC — 从应用程序启动到采样时发生 Full GC 的次数
FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
jstat -class pid:显示加载class的数量,及所占空间等信息。
jstat -compiler pid:显示VM实时编译的数量等信息。
jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。
jstat -gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使 用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推, OC是old内纯的占用量。
jstat -gcnew pid:new对象的信息。
jstat -gcnewcapacity pid:new对象的信息及其占用量。
jstat -gcold pid:old对象的信息。
jstat -gcoldcapacity pid:old对象的信息及其占用量。
jstat -gcpermcapacity pid: perm对象的信息及其占用量。
jstat -util pid:统计gc信息统计。
jstat -printcompilation pid:当前VM执行的信息。
除了以上一个参数外,还可以同时加上 两个数字,如:jstat -printcompilation 3024 250 6是每250毫秒打印一次,一共打印6次,还可以加上-h3每三行显示一下标题。

4、Java线程查看工具——jstack

    jdk1.6推出了一个查看线程CPU使用率的工具——jstack。其可以查看当前web应用中存在的线程,以帮助定位程序中那些线程对CPU的使用率过高。
    其格式为 stack -l PID ,其他可以通过stack -h查看帮助文档。
 
    今天发现项目工程启动后,在未作任何操作的情况下javaw的CPU使用率一直50%,直觉感觉项目工程有问题了。于是用jstack查看当前所有线程,并一一排查可能的java类,发现启动加载的类里有人写死循环了。以下是找到的类:
以上LogQueue就是开发的类。
 
定位时可能麻烦,那么多线程哪个是呢?
一开始我用jconsole观察,虽然也能看到这些线程,但其过滤功能太弱,无法找到公司的类。于是用jstack将结果写入文件,直接查找公司哪些类里的线程在运行。
通常框架里的类不会有问题,查找定位时可先放弃,如图中quartz框架的类,都可直接跳过。
   另外,在AIX下的jdk1.6中没找到jstack,不知道什么原因;后来在同事window系统jdk1.6中找到了。

5、GC的观察(经验)

(1)young gc每次的时间要在0~10ms内
(2)full gc每次的时间要在100~200ms之内
(3)做所有gc的时间相比程序运行起来之后的总时间(top中TIME+列中可查到)的比例要在5%之内
 CMS,全称Concurrent Low Pause Collector,是jdk1.4后期版本开始引入的新gc算法,在jdk5和jdk6中得到了进一步改进,它的主要适合场景是对响应时间的重要性需求 大于对吞吐量的要求,能够承受垃圾回收线程和应用线程共享处理器资源,并且应用中存在比较多的长生命周期的对象的应用。
  CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样:    初始标记(CMS-initial-mark) -> 并发标记(CMS-concurrent-mark) -> 重新标记(CMS-remark) -> 并发清除(CMS-concurrent-sweep) ->并发重设状态等待下次CMS的触发(CMS-concurrent-reset)
    其中的1,3两个步骤需要暂停所有的应用程序线程的。第一次暂停从root对象开始标记存活的对象,这个阶段称为初始标记;第二次暂停是在并发标记之后, 暂停所有应用程序线程,重新标记并发标记阶段遗漏的对象(在并发标记阶段结束后对象状态的更新导致)。第一次暂停会比较短,第二次暂停通常会比较长,并且 remark这个阶段可以并行标记。