我有一个Java应用程序,该应用程序部署在两台计算机上,并根据指标(包括JMC)判断它们都几乎耗尽了内存,并且持续了很长时间.但是,这些应用程序可以正常运行,并且不会发生OutOfMemory错误.
这很混乱.您能解释为什么应用仍然没有OutOfMemory错误运行吗?为什么在内存接近极限之前没有释放内存?
PS这里是堆指标
解决方法:
这就是Java的内存管理的工作方式-基本上将垃圾回收延迟到必要时才开始,以希望应用程序在需要GC之前退出.
因此,它通常会选择从OS分配更多的内存,直到达到-Xmx或OS /总RAM限制所给定的限制为止,然后它才会执行主要的垃圾收集器运行.这些运行将释放一些内存,然后应用程序将运行更多时间,直到再次遇到限制.
如果应用程序逐渐需要更多的内存,则在达到内存限制后会发生的情况是,主要GC运行会越来越频繁(随着所需内存的增加,GC清除的内存减少),并且GC运行时间会更长.在某个时候,虚拟机可能开始在GC上花费的时间比在运行应用程序时花费更多.
这样,Java进程可能会运行很长时间(可能是“永远”)并消耗几乎所有可用的内存,而实际的应用程序却几乎没有实际的运行时间,因为几乎所有的CPU时间都花在GC中. Java可能会检测到这种情况并抛出java.lang.OutOfMemoryError消息GC超额限制已超过,但并非总是如此.
如果要诊断您的应用程序是在优化内存使用,还是实际上实质上是内存不足,则需要找出VM在GC中花费的时间以及趋势.一些可能的方式:
>与JConsole或VisualVM(均为JDK的一部分)连接,并检查GC运行(时间间隔和持续时间)
>如果您的Java应用程序是单线程的,一种更简单的方法是观察CPU负载-默认GC是多线程的,因此在GC运行期间,它通常将在更多处理器/内核上运行,并且CPU负载将超过100%一个单核(unix顶部为100%以上),而单线程应用程序最多只能导致单个核的100%负载.
标签:performance,java
来源: https://codeday.me/bug/20191108/2009391.html