为什么运行Java应用程序的机器几乎耗尽了物理内存,但仍能运行数周
我有一个Java应用程序,它部署在两台机器上,根据指标(包括JMC)判断,它们都几乎没有内存,并且持续了相当长的时间。但是,应用程序运行正常,不会发生OutOfMemory错误。 这令人困惑。你能解释一下为什么应用程序在没有OutOfMemory错误的情况下仍然运行吗?为什么内存没有比它如此接近极限时更早释放 PS这里是堆度量为什么运行Java应用程序的机器几乎耗尽了物理内存,但仍能运行数周,java,performance,Java,Performance,我有一个Java应用程序,它部署在两台机器上,根据指标(包括JMC)判断,它们都几乎没有内存,并且持续了相当长的时间。但是,应用程序运行正常,不会发生OutOfMemory错误。 这令人困惑。你能解释一下为什么应用程序在没有OutOfMemory错误的情况下仍然运行吗?为什么内存没有比它如此接近极限时更早释放 PS这里是堆度量 Java的内存管理就是这样工作的——它基本上会将垃圾收集延迟到必要时,希望应用程序在需要GC之前退出 因此,它通常会选择从操作系统分配更多内存,直到-Xmx或OS/to
Java的内存管理就是这样工作的——它基本上会将垃圾收集延迟到必要时,希望应用程序在需要GC之前退出 因此,它通常会选择从操作系统分配更多内存,直到
-Xmx
或OS/total RAM limit给出一个限制,然后才执行主要的垃圾收集器运行。这些运行将释放一些内存,然后应用程序将再运行一段时间,直到再次遇到限制
如果应用程序逐渐需要更多的内存,那么在达到内存限制后,主要GC运行将变得越来越频繁(随着所需内存的增加,GC清除的内存减少),GC运行将变得更长。在某个时刻,VM在GC中花费的时间可能比运行应用程序花费的时间更多
这样,Java进程可能会运行很长时间(可能是“永远”)并消耗几乎所有可用内存,而实际应用程序几乎没有实际运行时间,因为几乎所有的CPU时间都花费在GC中。Java可能会检测到这种情况并抛出Java.lang.OutOfMemoryError
,其中消息GC开销限制超过了
,但并不总是这样
如果你想诊断你的应用程序是否只是在优化内存使用,或者实际上是内存不足,你需要了解VM在GC中花费了多少时间,以及趋势是什么。一些可能的方法:
- 连接JConsole或VisualVM(两者都是JDK的一部分)并检查GC运行(间隔和持续时间)
- 如果Java应用程序是单线程的,一种更简单的方法是观察CPU负载-默认GC是多线程的,因此在GC运行期间,它将主要在更多处理器/内核上运行,CPU负载将超过单个内核的100%(>100%在unix
),而单线程应用程序只会导致单个内核的负载高达100%top
-XX:MaxMetaspaceSize=512m
开关。让我知道它是否有效。我来回答一下。延迟GC的一个更重要的原因是以后的GC通常可以收集更多的垃圾。