【问题标题】:why running garbage collector sometimes increase reserved ram java?为什么运行垃圾收集器有时会增加保留的 ram java?
【发布时间】:2020-12-31 09:34:28
【问题描述】:

我们有一个 java8 Web 应用程序在 tomcat8.5.47 服务器上运行。我们每次只有 20-60 个用户会话,但大多数时候在服务器上上传文件高达 600mb。我们还使用休眠和 c3p0 来管理数据库连接。 我们监控服务器几天,发现有时java预留内存突然增加,垃圾收集器没有释放它。我们该如何管理?有没有办法释放预留内存并防止tomcat增加内存?还有什么方法可以减少任务管理器中使用的内存?

这些是我们的设置:

-XX:MaxPermSize=1g  -XX:+UseG1GC  -XX:+UseStringDeduplication  -XX:MaxHeapFreeRatio=15  -XX:MinHeapFreeRatio=5  -XX:-UseGCOverheadLimit  -Xmn1g  -XX:+UseCompressedOops  -Xms10g  -Xmx56g

这是发生这种情况时的分析器图像:

它是分析器的图像,也是 2 小时后的任务管理器:

附:我们使用 jprofiler 进行分析,绿色表示保留的 ram,蓝色表示已使用的 ram。在第二个框中您可以跟踪 gc 活动,第三个用于类,第四个显示线程活动,最后一个用于 cpu 活动。
谢谢大家的回答。

【问题讨论】:

  • 确定任务管理器会报告 RAM 使用情况吗?即:常驻内存?我非常怀疑
  • 我不知道。但问题是当任务管理器显示高达 56g 的内存时,cpu 使用率也会增加,我们检测到服务器速度很慢。这些数量每小时增加一次是否正常?
  • 这里显然缺少了一些东西,但是如果你不希望 JVM 分配一个 56GB 的堆,你为什么告诉它它可以呢?
  • 如果答案是“因为它需要 20-60 个用户的 56GB 堆”,我很想先解决这个问题!
  • 正如我在 cmets 中所说,我们知道 56g 很大,也知道有问题,但我们必须这样做,因为当任务管理器上显示的 ram 数量增加时,cpu 使用率也会上升,我们在重新启动 tomcat 之前检测缓慢。所以我们必须增加堆大小以推迟这些重新启动,然后尝试解决问题。

标签: java hibernate memory-management garbage-collection tomcat8


【解决方案1】:

即使 JVM 不需要,Java8 也不会将分配的 RAM 返回给操作系统。对于该功能,您需要迁移到另一个版本的 JDK。这是https://openjdk.java.net/jeps/346 的 JEP,它说它是在版本 12 中交付的,所以我认为版本 12 之后的 JDK 应该具有该功能。 防止保留内存增加的唯一方法是减小 Xmx 值。而且由于您将其设置为 56g,我假设您可以接受 Tomcat 消耗高达 56g 的内存。因此,如果您认为它太多,那么只需减少该数字即可。

【讨论】:

  • 1) 当然是it does release memory back。 2)“Java8不会将分配的RAM返回给操作系统” - 所以......一旦一个进程使一些内存驻留,它就永远不会把它还给它?这当然是非常不准确的(而且您也会混淆术语)。由于您已经链接了该 JEP,您可能会再次阅读它: ...collector may not return committed Java heap memory .... 3) 防止增加保留内存的唯一方法 - 增加“保留内存”绝对没问题。
【解决方案2】:

这些类型的问题绝非易事,主要是因为要“正确”回答问题,提出问题的人需要对操作系统如何处理和处理内存有一些基本的了解;以及存在不同类型的内存(至少residentcommittedreserved)的事实。到目前为止,我还不够多才多艺,无法完全正确地做到这一点,但我一直在学习并在这方面做得更好。它们意味着非常不同的东西,其中一些通常是无关紧要的(我发现reserved 就是这样)。您正在使用 Windows,因此 this, imho 是必须注意的开始。

看完之后,您需要转到 JVM 世界以及 JVM 进程的方式。堆由垃圾收集器管理,因此要缩小一些未使用的堆 - GC 需要能够做到这一点。虽然,before jdk-12,G1 可以做到这一点 - 它从来没有非常渴望。从 jdk-12 开始,有这个 JEP 将返回内存,即:它将 un-commit 内存返回。不过,请务必在发生这种情况时阅读。另请注意,像Shenandoah 和/或ZGC 这样的其他 收集器更经常这样做。

当然,因为你禁用了-UseGCOverheadLimit,你会得到一个巨大的 CPU 峰值(GC 线程疯狂地运行以释放空间),当然一切都变慢了。如果我是你,我会启用那个,让 GC 失败并分析 GC 日志以了解发生了什么。 56GB 的堆对于 20-60 个用户来说是一个巨大的数字(这看起来肯定像泄漏?)。请注意,如果没有 GC 日志,这可能无法给出解决方案。

附:查看您共享的第一个屏幕,注意那里有两种颜色:绿色和蓝色。我不知道那是什么工具,但看起来绿色代表“保留内存”,蓝色代表“已使用”(this is what used means)。但是,如果你能准确地说出它们是什么,那就太好了。

【讨论】:

  • 是的,你的权利。我知道 56g 是巨大的,但我们确实没有选择防止服务器变慢,有时需要每周或 4 天重新启动 tomcat。我们没有为我们必须的服务器选择 windows。此外,我们为提高代码性能和选择正确的设置做了很多工作,但我们需要做更多工作,我们知道这一点。如果您能通过介绍有用的资源来帮助我们,我们很想知道更多。非常感谢。
  • @leilas 我已经提出了我的想法 - 让它失败并进行堆转储。分析失败的地方和原因,说实话,我看不到其他选择。
猜你喜欢
  • 1970-01-01
  • 2014-11-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-30
  • 2015-03-22
  • 2020-03-06
  • 2022-01-12
  • 2017-03-02
相关资源
最近更新 更多