我们有一个通过 JMX 监控的服务。JVM 堆使用量正在增长,甚至主要收集都无法删除垃圾。检查堆会显示由 RMI 相关引用组成的垃圾(如果不是全部,主要是相关的类加载器)。缓解此问题的唯一方法是通过 JMX 发出显式 gc 调用(删除所有累积的垃圾)。我们的 gc 相关选项是:
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=1
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
而且我们还没有触及: DisableExplicitGC 或 sun.rmi.dgc.server.gcInterval
我相信这个问题应该由 sun.misc.GC.Daemon 中的代码解决:
public void run() {
for (;;) {
long l;
synchronized (lock) {
l = latencyTarget;
if (l == NO_TARGET) {
/* No latency target, so exit */
GC.daemon = null;
return;
}
long d = maxObjectInspectionAge();
if (d >= l) {
/* Do a full collection. There is a remote possibility
* that a full collection will occurr between the time
* we sample the inspection age and the time the GC
* actually starts, but this is sufficiently unlikely
* that it doesn't seem worth the more expensive JVM
* interface that would be required.
*/
System.gc();
d = 0;
}
/* Wait for the latency period to expire,
* or for notification that the period has changed
*/
try {
lock.wait(l - d);
} catch (InterruptedException x) {
continue;
}
}
}
}
由于某种原因,上面的 System.gc 没有被调用(已经通过查看 gc 日志进行了验证)。有人对如何解决这个问题有建议吗?