当我测试部署在 tomcat 中的应用程序时,该应用程序被挂起。我并排运行visualvm。在应用程序挂起期间,我在 visualvm 中看到垃圾收集正在进行。我从理论上读过,当垃圾收集开始工作时,系统会因为应用程序线程在此期间停止而停止。我想弄清楚
其他开发人员如何处理这种情况?
如何在不影响系统性能的情况下有效地处理它?
可以将其视为内置的固有属性还是可以有其他有效的解决方案?.
因为,JVM 可以配置不同的垃圾收集器算法,但在某些情况下它必须运行。如果我的理解有误,请纠正我。
当我测试部署在 tomcat 中的应用程序时,该应用程序被挂起。我并排运行visualvm。在应用程序挂起期间,我在 visualvm 中看到垃圾收集正在进行。我从理论上读过,当垃圾收集开始工作时,系统会因为应用程序线程在此期间停止而停止。我想弄清楚
其他开发人员如何处理这种情况?
如何在不影响系统性能的情况下有效地处理它?
可以将其视为内置的固有属性还是可以有其他有效的解决方案?.
因为,JVM 可以配置不同的垃圾收集器算法,但在某些情况下它必须运行。如果我的理解有误,请纠正我。
您的应用程序挂起,因为 GC 花费的时间太长。我建议您进行应用程序性能分析并尝试了解为什么您的应用程序需要 GC 运行这么长时间。寻找不必要的分配、未使用的对象、在没有任何控制的情况下超出的集合。
我有时会遇到这个问题。该解决方案总是涉及基于应用程序性能分析的某种优化(我在不同场合使用过 New Relic 和 AppDynamics)。
首先回答您的主要问题:不,您不必接受您的应用程序挂起。你实际上可以做点什么。但是,有很多方法可以微调垃圾收集器,包括调整代码和使用直接控制 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 负责时(通常情况并非如此 - 几乎总是首先要调整其他事情),我研究使用子类Reference
来帮助我在不同的负载之间分配负载GC 运行,例如,我会检查是否使用 aWeakHashMap
而不是 another有Map
帮助。
我只将 JVM 调优作为最后的手段。通常很难记录为什么以及如何 使用-XX:MaxNewSize
或-XnoClassGC
应该使用参数,而且我真的不希望供应链下游的人们在不了解问题的根本原因的情况下自己开始尝试 GC 调整。
当我真的看不到其他选项时,我首先尝试使用-Xms
and -Xmx
-减小堆大小有时可以提高垃圾收集性能,这也很容易解释。将起始堆大小设置为最大堆大小可确保不会因新的内存分配而导致暂停 - 随后可能会重新排列堆内容。我使用效果良好的其他设置是-XX:+UseParNewGC
和-XX:+UseTLAB
。
有两种方法可以解决这个问题:
您可以通过选择“低暂停”收集器和/或更改各种调整选项来调整 JVM 的垃圾收集子系统。不幸的是,低暂停收集是有代价的。您可以减少 GC 运行时系统暂停的时间长度,但另一方面是更多的 CPU 周期总体上花费在垃圾收集和相关事情上。
您可以调整您的应用程序以减少它创建的(长期存在的)垃圾量以及它泄漏的内存量。但是,您在这里也需要小心……因为一些经典策略(对象池、基于弱/软引用的缓存)实际上会使事情变得更糟。至少在尝试减少分配之前,您应该先进行概要分析。
还有其他可能的解释:
“挂起”可能是无关的。他们可能是由于与缓慢的外部资源交谈。它们可能是线程瓶颈的不幸副作用。
“挂起”可能是系统作为一个整体“抖动”引起的。当您尝试使用无法全部放入物理内存的堆时,就会发生这种情况。然后系统必须根据需要在物理内存和磁盘之间交换虚拟内存页面。垃圾收集(尤其是“完整”GC)很可能会触发这种情况。