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

标签 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


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

enter image description here

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

最佳答案

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

试图避免对“旧代”(应用程序持有一段时间的永久对象,例如来自用户 session 、缓存或某种内存泄漏)的垃圾收集必须在单个经典 FullGC 中完成在您的应用程序被卡住而必须清理整个堆的情况下(这取决于对象的数量,这可能需要很长时间,比如几秒钟。阅读所有相关信息 here ,引用其中的一句话:

The goal is to reclaim as much heap space as possible (starting with those regions that contain the most reclaimable space) while attempting to not exceed the pause time goal



您为以下设置的 40%:InitiatingHeapOccupancyPercent与(整个)堆占用率相关并表示何时开始并发 GC 周期(这应该在日志中可见,如果没有看到: this related question )。基于整个堆的占用率而不只是其中一代(因此不仅仅是 Old Gen)(包括 G1)的占用率触发并发 GC 周期的 GC 使用此选项。值 0 表示“执行恒定的 GC 循环”。默认值为 45。(改编自:Oracle® Communications WebRTC Session Controller System Administrator's Guide)

所以有可能:
  • GC 周期以 40% 的堆占用率启动,但在完成之前您会达到更高的水平(例如 90%),只要您的应用程序正在运行,这可能完全没问题
  • 您有某种内存泄漏(但如果不知道应用程序及其运行时长或长时间后运行情况,则很难从图表中看出这一点)
  • 可能还有一些其他问题,但如果没有垃圾收集日志来分析是无法判断的,但您可能需要引用:Monica Beckwith's article on G1GC例如Evacuation Failure 上的部分

  • 如果您真的希望您的应用程序使用更少的内存(可能会以性能/吞吐量的一些损失为代价),您可以降低 MaxHeapSize(但您应该使用以下任一种:MaxRAMFraction 或 MaxHeapSize (XmX),而不是两者)。

    或者根据您的应用程序和性能要求,考虑使用完全不同的 JVM/垃圾收集器,例如:
  • IBM/Eclipse OpenJ9(参见:https://developer.ibm.com/articles/garbage-collection-tradeoffs-and-tuning-with-openj9/,它被吹捧为具有非常低的内存开销)
  • 或本研究中提到的任何其他关于 Java 内存弹性的 GC discussing Shenandoah, ZGC, C4 and many others
  • 关于java - InitiatingHeapOccupancyPercent 设置为 40 但旧代内存在 G1GC 中超过 60%,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61456651/

    相关文章:

    java - 将领域对象映射到服务层或Web层中的资源对象?

    memory-management - 查找 Solaris 中从虚拟页到物理页的映射

    ruby-on-rails - Heroku 跟踪唯一请求 Id

    java - 为什么我使用G1GC时Scan RS花费很长时间

    java - 使用接口(interface)时如何为类赋值?

    java - 小数点后的固定位数

    java - 铁路网图

    c++ - QWizard会删除QWizardPage还是会泄露?

    java - Intellij Idea15 CE 无法启动 -XX :+UseG1GC

    java - 为什么看似不必要地触发 G1 Full GC?