我正在尝试解决我的 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 后堆的下限在增加,我的图看起来像这样:
您能否建议我的堆参数是否正确以及它们的配置方式是否存在冲突,或者如何减少使用的最大堆?
最佳答案
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)所以有可能:
Evacuation Failure
上的部分如果您真的希望您的应用程序使用更少的内存(可能会以性能/吞吐量的一些损失为代价),您可以降低 MaxHeapSize(但您应该使用以下任一种:MaxRAMFraction 或 MaxHeapSize (XmX),而不是两者)。
或者根据您的应用程序和性能要求,考虑使用完全不同的 JVM/垃圾收集器,例如:
关于java - InitiatingHeapOccupancyPercent 设置为 40 但旧代内存在 G1GC 中超过 60%,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61456651/