Java G1 GC Processing Reference对象运行缓慢

我在Java上运行了反击。 它工作24小时,每秒约100次。 在白天,GC处理时间从20-60毫秒缓慢上升到10000-60000毫秒,然后下降到20-60毫秒。 这种模式不时重复。 从GC日志中我发现GC主要用于处理Reference对象(Ref Proc)。 那么这么长的GC时间的原因是什么?

Server: Amazon EC2 m1.small OS: Ubuntu 10.04.3 LTS Java: Oracle 1.7.0_07 

GC日志示例:

 2012-09-13T16:51:20.091+0400: 167239.936: [GC pause (young), 62.58395400 secs] ... [Other: 62489.7 ms] [Choose CSet: 0.0 ms] [Ref Proc: 62433.9 ms] [Ref Enq: 0.0 ms] [Free CSet: 0.7 ms] [Eden: 200M(200M)->0B(199M) Survivors: 4096K->5120K Heap: 578M(1024M)->380M(1024M)] 

时间 – “Ref Proc”图表:

 09:37:59 - 242.4 ms 09:38:50 - 226.0 ms 09:39:00 - 83.6 ms ... 11:45:22 - 451.8 ms 11:46:04 - 489.3 ms 11:46:46 - 505.6 ms ... 14:05:40 - 1027.3 ms 14:06:01 - 796.6 ms 14:06:35 - 1064.0 ms ... 15:44:32 - 1920.4 ms 15:45:04 - 2116.7 ms 15:45:39 - 2196.8 ms ... 16:19:07 - 3983.3 ms 16:19:43 - 4494.9 ms 16:20:16 - 4065.2 ms ... 16:33:11 - 7690.1 ms 16:33:50 - 8501.4 ms 16:34:28 - 8059.3 ms ... 16:47:14 - 51378.6 ms 16:49:11 - 57529.2 ms 16:51:20 - 62433.9 ms 16:53:00 - 46.1 ms 16:53:30 - 45.5 ms 16:54:03 - 45.0 ms ... 16:54:38 - 57.0 ms 16:55:09 - 20.9 ms 16:55:43 - 21.3 ms ... 16:09:45 - 134.3 ms 16:10:21 - 142.1 ms 16:10:58 - 147.5 ms ... 17:18:51 - 177.3 ms 17:19:27 - 135.8 ms 17:20:03 - 179.6 ms 

我在java源代码中找到了参数PrintReferenceGC。 GC日志显示下一步

 [SoftReference, 0 refs, 0.0000050 secs] [WeakReference, 6 refs, 0.0000030 secs] [FinalReference, 113 refs, 0.0011180 secs] [PhantomReference, 0 refs, 0.0000020 secs] [JNI Weak Reference, 3.9010450 secs] 

这是JNI弱参考的一些问题。

重要的是我的所有运行都是使用Yourkit分析器。 我安装了OpenJDK7的fastdebug构建。 在这个版本中有一个参数-XX:+ TraceReferenceGC。 运行此参数后,gc log显示约5000个终结器。 通过关闭Yourkit的套接字探针解决了此问题。

作为第一步,您可以使用VisualVM或任何工具来分析堆使用模式。 您可以通过优化代码,检查对象创建的热点以及应该是永久解决方案来获得解决方案。

如果不可能,您必须找到最适合的堆大小和适合您的应用程序行为的GC算法。 这将是一种试错法。 你肯定必须通过调整doc 。 当您的应用程序行为发生更改或加载模式更改时,您现在进行的调整可能会再次变得低效。

尝试为您找到合适的collections家。 你将调整一些参数,如

  -XX:+UseConcMarkSweepGC -XX:SurvivorRatio=10 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=30 

通过反复试验。

Interesting Posts