java - 为什么即使有大量未使用的内存也会发生 GC

标签 java garbage-collection jvm newrelic

enter image description here ( promise 线和最大线相同)

我正在查看 newrelic 中 Java 应用程序的内存使用情况。这里有几个问题:

#1

过去几天,提交的 PS Survivor 空间堆发生了变化。但既然它是由 JVM 配置的,那么它应该是一个常量吗?

#2

据我了解,当有垃圾收集时,堆内存应该减少。当发生major gc或minor gc时,Eden的内存可能会减少,而当发生major gc时,Old的内存可能会减少。

但是如果您查看内存使用情况,在 6 月 6 日到 7 日之间的某个时间,内存会上升,然后又下降。这应该代表发生了一次重大GC,对吗?然而,仍然有大量未使用的内存。看起来还没有快到极限。那么major gc是如何触发的呢? Eden 内存使用情况也是如此,它从未达到限制,但仍然减少。

应用程序从其他地方获取文件。该文件可能很大并且需要在内存中处理。这能解释上面的问题吗?

最佳答案

您需要提供有关您的配置的更多信息才能明确回答这个问题,我假设您正在使用 Oracle 的 Hotspot JVM 并且您正在使用 G1 收集器。发布启动 JVM 所用的标志也很有用。

  1. 这里的关键词是“ promise ”。这是JVM保留的内存,但不一定在使用(甚至映射到物理页,它只是JVM可以使用的虚拟内存范围)。 java.lang.management 包的 MemoryUsage 类对此有很好的描述(查看 API 文档)。它说,“提交代表保证可供Java虚拟机使用的内存量(以字节为单位)。提交的内存量可能会随着时间的推移而变化(增加或减少)。Java虚拟机可能会释放内存到系统...”这就是您看到它发生变化的原因。

  2. 假设您使用的是 G1,则收集器执行增量压缩。您是正确的,如果收集器无法跟上旧一代中的分配并且空间不足,它将执行完整的压缩收集。这里没有发生这种情况,因为最后一张图显示您没有使用分配的堆空间。但是,为了避免这种情况,G1 将与您的应用程序同时进行收集和压缩。这就是为什么您会看到使用率上升(当您的应用程序实例化更多对象时)然后下降(当 G1 收集器从不再需要的对象中回收空间时)。有关 G1 如何工作的更详细说明,请阅读文档 https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc.html .

关于java - 为什么即使有大量未使用的内存也会发生 GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44509036/

相关文章:

java - *您*使用哪个 Java 调试器

java - ArrayList.toArray() 抛出 NullPointerException

ruby - GC.disable 的任何性能缺点?

visual-studio - 是否可以实现 GC.GetAliveInstancesOf<T>() (用于调试)?

java - Java 字节码助记符与 Jasmin 有何不同?

c# - 通过 C# 运行 weka

java - 将镜像快速启动 Java 项目上传到 App Engine :

java - JAI 关闭文件句柄是否为时过早?

java - 如何识别 Java 字节码中的覆盖方法?

multithreading - 多线程中未知进程的高CPU使用率