InitiatingHeapOccupancyPercent 设置为 40 但旧代内存在 G1GC 中超过 60%

Ama*_*ngh 5 java memory-management g1gc

我正在尝试解决我的 Java 服务中堆内存超过 90% 的问题。

下面是我正在使用的堆配置,

-Xms6144m \
                -Xmx6144m \
                -verbose:gc \
               -XX:G1HeapRegionSize=2097152 \
               -XX:+PrintGC \
               -XX:+PrintFlagsFinal \
               -XX:InitiatingHeapOccupancyPercent=40 \
               -XX:NewRatio=2 \
               -XX:+PrintGCDetails \
               -XX:+PrintGCDateStamps \
               -XX:+PrintAdaptiveSizePolicy \
               -XX:+PrintTenuringDistribution \
               -XX:+UseGCLogFileRotation \
               -XX:NumberOfGCLogFiles=10 \
               -XX:GCLogFileSize=50M \
    -XX:+UnlockExperimentalVMOptions \
  -XX:+UseG1GC -XX:+UseStringDeduplication \
  -XX:+UseCGroupMemoryLimitForHeap \
  -XX:+ParallelRefProcEnabled
  -XX:+OptimizeStringConcat
  -XX:MaxRAMFraction=2 \
  -XshowSettings:vm

Run Code Online (Sandbox Code Playgroud)

问题是我的老一代逐渐被填满,随着时间的推移,GC 后堆的下限在增加,我的图看起来像这样:

在此处输入图片说明

您能否建议我的堆参数是否正确以及它们的配置方式是否存在冲突,或者如何减少使用的最大堆?

Joh*_*esB 2

G1GC 主要是为了一件事而设计的,通过以下方式保持应用程序的响应能力:

\n\n

试图避免“旧一代”(应用程序已保留一段时间的终身对象,例如来自用户会话、缓存或某种内存泄漏)的垃圾收集必须在单个经典 FullGC 中完成您的应用程序被冻结,而整个堆必须被清理(这取决于对象的数量,可能需要很长时间,例如几秒钟)。请在此处阅读所有内容阅读所有内容,引用其中的一段话:

\n\n
\n

目标是回收尽可能多的堆空间(从包含最多可回收空间的区域开始),同时尝试不超过暂停时间目标

\n
\n\n

您为以下设置的 40%:InitiatingHeapOccupancyPercent与(整个)堆占用率相关,并表示何时启动并发 GC 周期(这应该在日志中可见,如果没有看到:此相关问题)。根据整个堆的占用情况而不仅仅是某一代(因此不仅仅是 Old Gen)(包括 G1)的占用情况触发并发 GC 周期的 GC,包括 G1,都使用此选项。值 0 表示“进行恒定的 GC 循环”。默认值为 45。(改编自:Oracle\xc2\xae Communications WebRTC Session Controller System Administrator\'s Guide

\n\n

所以有可能:

\n\n
    \n
  1. GC 周期在堆占用率为 40% 时启动,但在完成之前您会达到更高的水平(例如 90%),只要您的应用程序正在运行,这可能完全没问题
  2. \n
  3. 您存在某种内存泄漏(但是,如果不知道应用程序及其运行时间,或者不知道它在较长时间后如何发挥作用,则很难从图表中看出这一点)
  4. \n
  5. 可能还有其他一些问题,但如果没有垃圾收集日志来分析,就无法判断,但您可能需要参考:Monica Beckwith 的关于 G1GC 的文章例如Evacuation Failure
  6. \n
\n\n

如果您确实希望应用程序使用更少的内存(可能会以性能/吞吐量损失为代价),您可以降低 MaxHeapSize(但您应该使用 MaxRAMFraction 或 MaxHeapSize (XmX) 之一,而不是同时使用两者)。

\n\n

或者根据您的应用程序和性能要求,考虑使用完全不同的 JVM/垃圾收集器,例如:

\n\n\n