当我测试在tomcat中部署的应用程序时,该应用程序被挂起。并排我正在运行visualvm。在应用程序挂起期间,我在visualvm中看到垃圾收集正在进行中。我在理论上已经读过,当垃圾收集开始工作时,系统会停止,因为应用程序线程在这段时间内停止。
我希望得到清晰的想法其他开发者如何处理这种情况?
如何在不影响系统性能的情况下以有效的方式处理它?</ strong>
可以将其视为内置固有属性还是可以有其他有效的解决方案?。
因为,JVM可以配置不同的垃圾收集器算法,但在某些时候它必须运行。如果我理解错了,请纠正我。
答案 0 :(得分:4)
您的应用程序暂停,因为GC耗时太长。我建议您进行应用程序性能分析,并尝试理解为什么您的应用程序需要GC运行这么长时间。寻找不必要的分配,未使用的对象,在没有任何控制的情况下长大的集合。
我有时会遇到这个问题。该解决方案总是涉及基于应用程序性能分析的某种优化(我在不同场合使用过New Relic和AppDynamics)。
答案 1 :(得分:3)
首先回答您的主要问题:不,您不必接受您的应用程序挂起。你可以真正做点什么。但是,有许多方法可以通过调整代码和使用直接控制GC策略的JVM开关来微调垃圾收集器。然而,这是一个广泛的主题,没有一个单一的最佳答案。这取决于您的应用程序和您的环境。你能做的最好的事情就是教育自己,关于它:
1。)在此处获取概述:http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html
2.)阅读具体的调整方案:
http://www.jaspersoft.com/sunopenjdk-jvm-garbage-collection-tuning-tutorial
http://www.theserverside.com/news/thread.tss?thread_id=63241
3.)阅读关于同一主题的其他SO问题。
以下是我在自己的代码中使用的一些规则:
我从不尝试通过“在适当的时候”手动调用System.gc()
来改善GC行为。如果将此与GarbageCollectorMXBean
和MemoryMXBean
等内容结合使用,可以超越垃圾收集器。
当我发现一个可重现的性能问题时,GC的责任(通常不是这种情况 - 几乎总是先调整其他东西),我会研究{{的子类的使用3}}帮助我在不同的GC运行之间分配负载,例如我会检查是否使用Reference
而不是其他Map
帮助。
我只是采用JVM调优作为最后的手段。通常很难记录为什么以及如何使用-XX:MaxNewSize
或WeakHashMap
之类的参数,而且我真的不希望人们在供应链的下游开始尝试使用GC调整自己,而我却没有理解问题的根本原因。
当我确实看不到其他选项时,我首先尝试使用-Xms
和-Xmx
- 有时缩小堆大小提高垃圾收集性能,这也很容易解释。将起始堆大小设置为最大堆大小可确保新内存分配不会导致暂停 - 可能是重新排列堆内容。我使用的其他设置包括-XnoClassGC
和-XX:+UseTLAB
。
答案 2 :(得分:3)
有两种方法可以解决这个问题:
您可以通过选择&#34;低暂停&#34;来调整JVM的垃圾收集子系统。收集器,和/或更改各种调整选项。不幸的是,低暂停收集会产生成本。减少GC运行时系统暂停的时间长度,但另一方面是垃圾收集和相关事情上花费了更多的CPU周期整体。
您可以调整应用程序以减少它创建的(长寿命)垃圾量以及泄漏的内存量。但是你也需要在这里小心......因为一些经典策略(对象池,基于弱/软引用的缓存)实际上可以使事情变得更糟。至少在尝试减少分配之前,您应首先进行分析。
还有其他可能的解释:
&#34;挂起&#34;可能是无关的。他们可能是因为谈论缓慢的外部资源。它们可能是导致线程瓶颈的不幸副作用。
&#34;挂起&#34;可能是整个系统造成的,并且会引起争议。当您尝试使用不符合物理内存的堆时会发生这种情况。然后,系统必须根据需要在物理内存和光盘之间交换虚拟内存页面。垃圾收集(特别是&#34;完全&#34; GC)很可能触发这一点。