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

tomcat每隔一小时full gc的问题》上有1条评论

  1. 周亚国

    JBoss4.x,JBoss5.x中默认配置了sun.rmi.dgc.client.gcInterval与sun.rmi.dgc.server.gcInterval,默认是1小时,不过在JBoss AS 7.x中就没有了这两个配置。
    应用服务器只有暴露了rmi服务时(比如jndi服务),才会定时system.gc(),触发full gc
    JBoss AS 7中由于内部都采用了JBoss remoting框架,无rmi,所以没有定时1小时full gc的现象。

    回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注