【问题标题】:Why does the java8 GC not collect for over 11 hours?为什么 java8 GC 超过 11 小时不收集?
【发布时间】:2015-04-21 04:53:08
【问题描述】:
上下文:64 位 Oracle Java SE 1.8.0_20-b26
11 多个小时以来,我正在运行的 java8 应用程序一直在 Tenured 代中积累对象(接近 25%)。因此,我手动单击了 jconsole 中的Perform GC 按钮,您可以在图表右侧看到堆内存的急剧下降。除了XX:NewRatio=2,我没有打开任何特殊的虚拟机选项。
GC为什么不清理tenured generation?
【问题讨论】:
标签:
garbage-collection
java-8
【解决方案1】:
这是一个完全预期的和理想的行为。 JVM 一直通过及时执行 Minor GC 成功地避免了 Major GC。根据定义,Minor GC 不会触及 Tenured Generation,而分代垃圾收集器背后的关键思想正是这种模式将会出现。
您应该对您的应用程序运行良好感到非常满意。
【解决方案2】:
吞吐量收集器的主要目标,顾名思义,就是吞吐量(通过GCTimeRatio)。它的次要目标是暂停时间 (MaxGCPauseMillis)。只有tertiary goal 才会考虑保持低内存占用。
如果您想实现较小的堆大小,则必须放宽其他两个目标。
您可能还希望降低 MaxHeapFreeRatio 以允许 JVM 将内存归还给操作系统。
【解决方案3】:
GC为什么不清理tenured generation?
因为它不需要。
看起来您的应用程序正在以相对较慢的速度累积永久垃圾,并且仍然有足够的空间用于永久对象。 “吞吐量”收集器通常仅在空间填满时运行。就 CPU 使用而言,这是最有效的……这就是吞吐量收集器优化的目标。
简而言之,GC 正在按预期工作。
如果您担心正在使用的内存量(因为没有收集永久空间),您可以尝试使用较小的堆运行应用程序。但是,该图表明应用程序的初始行为可能与其稳态行为有很大不同。换句话说,您的应用程序可能需要一个大堆开始。如果是这种情况,那么减小堆大小可能会使应用程序停止工作,或者至少会使启动阶段变慢很多。