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