tomcat每隔一小时full gc的问题

关于gc信息的收集,除了在启动时设置gclog选项,对于已经启动的java进程,也可以通过jstat去查看gc发生的原因。

$ jstat -gccause  java_pid 1s

S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
0.00 100.00  31.17  74.24  98.80      7    0.045     1    0.176    0.221 Allocation Failure   No GC
0.00 100.00  32.61  74.24  98.83      7    0.045     1    0.176    0.221 Allocation Failure   No GC
73.65   0.00  0.00  74.24  99.73      8    0.052     2    0.176    0.228 No GC      System.gc()
0.00   0.00   1.44  87.57  65.40      8    0.052     2    0.395    0.447 System.gc()          No GC
0.00   0.00   1.44  87.57  65.40      8    0.052     2    0.395    0.447 System.gc()          No GC
0.00   0.00   1.44  87.57  65.40      8    0.052     2    0.395    0.447 System.gc()          No GC

有一些应用周期性的发生full gc,即使没有多大访问量的情况,在tomcat里可能有2种原因:

1) 预防内存泄露的监听器 JreMemoryLeakPreventionListener 每隔一小时触发一次System.gc

Class clazz = Class.forName("sun.misc.GC");
Method method = clazz.getDeclaredMethod(
                        "requestLatency",
                        new Class[] {long.class});
method.invoke(null, Long.valueOf(3600000)); // 一小时

去看sun.misc.GCrequestLatency方法,传入的参数表示一次gc请求的延迟时间。会有个低优先级的daemon线程设置一个不超过这个延迟时间的object-inspection的周期

/**
 * Makes a new request for a garbage-collection latency of the given
 * number of real-time milliseconds.  A low-priority daemon thread makes a
 * best effort to ensure that the maximum object-inspection age never
 * exceeds the smallest of the currently active requests.
 *
 * @param   latency
 *          The requested latency
 *
 * @throws  IllegalArgumentException
 *          If the given <code>latency</code> is non-positive
 */
public static LatencyRequest requestLatency(long latency) {
    return new LatencyRequest(latency);
}

Daemon线程里,会在object-inspection周期之后执行System.gc()的。在tomcat 7028 和 6036 之后的版本里,把延迟时间调整了,不会再每小时调用一次了:

method.invoke(null, Long.valueOf(Long.MAX_VALUE - 1));

2) rmi.dgc 在JDK6里默认是1小时

参考这里,可以通过系统参数修改:

-Dsun.rmi.dgc.client.gcInterval=72000000
-Dsun.rmi.dgc.server.gcInterval=72000000

分享ppt: jvm内存管理

去年分享的,里面的一些参数与当前线上的实际情况可能已对不上,仅供参考。

slideshare下载,或微盘下载

希望你能借鉴里面使用scala repl(再配合其他工具如jconsole)来做jvm参数调节的测试,比如:

repl很适合做诸如此类的测试。