我有一个Java客户端,它从服务器中消耗大量数据。如果客户端无法以足够快的速率跟上数据流,则服务器会断开套接字连接。我的客户每天断开连接几次。我运行jconsole来查看内存使用情况,堆空间图看起来像一个相当明确的锯齿模式,在大约0.5GB和1.8GB之间振荡(分配2GB的堆空间)。但每次断开连接都是在完整的GC期间(但不是每个完整的GC)。我看到完整的GC平均需要1秒多一点。根据一天中的时间,完整的GC会在忙碌时每5分钟发生一次,或者在缓慢的时间段内可以在完整的GC之间进行30分钟。
我怀疑如果我可以减少完整的GC时间,客户端将能够更好地跟上传入的数据,但我没有太多的GC调整经验。有没有人知道这是否是一个好主意,以及如何做到这一点?或者是否有另一种可能有效的想法?
**更新** 我使用-XX:+ UseConcMarkSweepGC并且它有所改进,但在非常忙碌的时刻我仍然断开连接。因此,我将堆分配增加到3GB,以帮助度过忙碌的时刻,现在看起来好像很好,但它只有1天没有断开连接。也许如果我得到一些时间,我会经历并尝试减少创建的垃圾量,我相信也会有所帮助。感谢您的所有建议。
答案 0 :(得分:12)
完整的GC可能需要很长时间才能完成,并且不容易调整。
(轻松)调整它的一种方法是增加堆空间 - 一般来说,堆空间的两倍可以使两个GC之间的间隔加倍,但会使GC消耗的时间加倍。如果您运行的程序具有非常明确的使用模式,也许您可以考虑增加堆空间以使间隔如此之大,以至于您可以保证有一些空闲时间来尝试使系统执行GC。另一方面,遵循这个逻辑,如果堆很小,一个完整的垃圾收集将立即完成,但这似乎比帮助更多的麻烦。
此外,-XX:+UseConcMarkSweepGC
可能会有所帮助,因为它会尝试同时执行GC操作(不会停止您的程序;请参阅here)。
Here's Til Gene(Azul系统的首席技术官,高性能JVM的制造商,并发布了几个GC算法)的一个非常好的演讲,关于一般的JVM中的GC。
答案 1 :(得分:4)
调整Full GC并不容易。更好的方法是减少垃圾产生。减少垃圾产生的压力可以减少集合上的压力,使物体进入固定空间,收集成本更高。
我建议您使用内存分析器
通过减少您创建的垃圾量,对象更有可能在伊甸园或幸存者空间中死亡,这意味着您的完整集合要少得多,也可以缩短。
不要认为你必须忍受很多收藏,在极端情况下,你几乎可以完全避免它http://vanillajava.blogspot.ro/2011/06/how-to-avoid-garbage-collection.html
答案 2 :(得分:2)
取出对Runtime.getRuntime()的调用.gc() - 当手动触发垃圾收集时,它不执行任何操作,或者执行完全停止垃圾收集。您希望增量GC发生。
您是否尝试过使用jdk安装的服务器jvm?它改变了一堆默认配置设置(包括垃圾收集)并且很容易尝试 - 只需在你的java命令中添加-server。
java -server
创建的所有垃圾是什么?你能少生产吗?尽可能尝试使用valueOf方法。通过使用更少的内存,您将节省自己在gc和内存分配中的时间。