为什么运行垃圾收集器有时会增加Java的已保留内存?

huangapple go评论76阅读模式
英文:

why running garbage collector sometimes increase reserved ram java?

问题

以下是翻译好的内容:

我们有一个运行在Tomcat 8.5.47服务器上的Java 8 Web应用程序。每次我们只有20-60个用户会话,但大部分时间会上传高达600MB的文件到服务器上。我们还使用Hibernate和c3p0来管理数据库连接。

我们监控了服务器几天,发现有时候Java保留的内存突然增加,而垃圾收集器没有释放它。我们该如何管理这个问题?是否有办法释放保留的内存,并防止Tomcat增加内存?还有没有办法在任务管理器中减少已使用的内存?

以下是我们的设置:

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

以下是当发生此情况时的分析器图像:
为什么运行垃圾收集器有时会增加Java的已保留内存?

以下是2小时后的分析器图像和任务管理器图像:
为什么运行垃圾收集器有时会增加Java的已保留内存?

附注:我们使用JProfiler进行分析,绿色表示保留的内存,蓝色表示已使用的内存。在第二个框中,您可以跟踪垃圾回收活动,第三个框显示类信息,第四个框显示线程活动,最后一个框显示CPU活动。感谢大家的答复。

英文:

we have a java8 web application running on tomcat8.5.47 server.we have only 20-60 users sessions per time but most of time up to 600mb uploading files on server.we also use hibernate and c3p0 for manage database connections.
we monitored server several days and saw sometimes java reserved ram increased suddenly and garbage collector did not released it.how can we manage this?and is there any way to release reserved ram and prevent tomcat from increasing ram? and also any way to decrease used ram in task manager?

these are our settings:

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

and it is an image of profiler when this happened:
为什么运行垃圾收集器有时会增加Java的已保留内存?

and it is an image of profiler and also task manager after 2 hours:
为什么运行垃圾收集器有时会增加Java的已保留内存?

P.s. we use jprofiler to profile and the green colour shows reserved ram and the blue colour is for used ram.also in second box you can track gc activity and third is for classes and forth shows threads activities and last is for cpu activities.
Thank you all for your answers.

答案1

得分: 2

这种类型的问题从来都不容易,主要因为要做到“正确”,提问者需要对操作系统如何处理和管理内存有一些基本的了解;而且事实上有着不同类型的内存(至少有“常驻内存”、“已分配内存”和“保留内存”)。我远远不足以完全正确地解释这些,但我在不断学习,对此也有了更好的理解。它们表示着非常不同的含义,其中一些通常是无关紧要的(我发现“保留内存”就是这样)。你正在使用 Windows,因此我认为 这个链接 是一个必须观看的起点。

在你观看完那个之后,你需要转向 Java 虚拟机(JVM)的世界,了解 JVM 进程是如何管理堆内存的。堆内存由垃圾回收器来管理,所以要收缩一些未使用的堆内存,垃圾回收器需要有这个能力。尽管在 jdk-12 之前,G1 回收器能够做到这一点,但它从来没有非常渴望这样做。从 jdk-12 开始,有一个 JEP 可以回收内存,即可以将内存“取消分配”。但请确保了解这是在什么时候发生的。此外,请注意,像 Shenandoah 和/或 ZGC 等其他回收器更经常地执行这项操作。

当然,由于你禁用了 -UseGCOverheadLimit,垃圾回收线程会疯狂运行以释放空间,导致 CPU 使用量急剧上升,当然一切都会变慢。如果我是你,我会将该选项重新启用,让垃圾回收失败,然后分析垃圾回收日志以了解发生了什么。对于 20-60 个用户来说,56GB 的堆内存是一个巨大的数字(这似乎确实像是一个内存泄漏?)。请注意,如果没有垃圾回收日志,可能很难提供一个解决方案。

附言:看一下你分享的第一个屏幕截图,注意那里有两种颜色:绿色和蓝色。我不知道那是什么工具,但绿色似乎表示“保留内存”,而蓝色表示“已使用”(这就是“已使用”的含义)。但如果你能准确地说明这些是什么,那会很好。

英文:

These types of questions are never easy, mainly because to get it "right", the person asking them needs to have some basic understanding of how an OS treats and deals with memory; and the fact that there are different types of memory (at least resident, committed and reserved). I am by far not versatile enough to get this entirely right too, but I keep learning and getting better at this. They mean very different things and some of them are usually irrelevant (I find reserved to be such). You are using windows, as such this, imho is a must watch to begin with.

After you watch that, you need to move to the JVM world and how a JVM process. The heap is managed by a garbage collector, so to shrink some un-used heap - the GC needs to be able to do that. And while, before jdk-12, G1 could do that - it was never very eager to. Since jdk-12, there is this JEP that will return memory back, i.e.: it will un-commit memory back. Be sure to read when that happens, though. Also notice that other collectors like Shenandoah and/or ZGC do it much more often.

Of course, since you disable -UseGCOverheadLimit, you get a huge spike in CPU (GC threads are running like crazy to free space) and of course everything slows down. If I were you, i would enable that one back, let GC fail and analyze GC logs to understand what is going on. 56GB of Heap is a huge number for 20-60 users (this surely looks like a leak?). Notice, that without GC logs, this might be impossible to give a solution to.

P.S. Look at the first screen you shared and notice how there are two colors there: green and blue. I don't know what tool is that, but it looks like green is for "reserved memory" and blue is "used" (this is what used means). But it would be great if you said exactly what those are.

答案2

得分: 1

Java8即使JVM不需要,也不会将分配的RAM返回给操作系统。如果要使用该功能,您需要切换到JDK的另一个版本。这是关于此功能的JEP链接:https://openjdk.java.net/jeps/346。据该链接所述,该功能在12版本中实现,因此我认为12版本之后的JDK应该都具备这个功能。
防止保留内存增加的唯一方法是减小Xmx的值。由于您将其设置为56g,我想您可能认为允许Tomcat使用高达56g的内存是可以的。因此,如果您认为这太多了,只需减少该数字。

英文:

Java8 doesn't return allocated RAM back to OS even if JVM doesn't need it. For that feature you need to move to another version of JDK. This is JEP for that https://openjdk.java.net/jeps/346 it says that it was delivered in version 12 so I assume JDKs with version after 12 should have that feature.
The only way to prevent increasing of reserved memory is to decrease Xmx value. And since you are setting it to 56g I assume you are OK with Tomcat consuming up to 56g of memory. So if you think that it is too much then just decrease that number.

huangapple
  • 本文由 发表于 2020年9月13日 21:07:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/63871149.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定