当前位置: 首页 > 知识库问答 >
问题:

Java进程中的OutOfMemoryException,但使用的堆大约是使用大小的一半

董高畅
2023-03-14

我们正在运行一个进程,该进程具有消耗大量内存的缓存。但缓存中的对象数量在执行期间保持稳定,而内存使用量却在无限制地增长。

我们已经运行了Java飞行记录器,以便尝试猜测正在发生什么。

在那份报告中,我们可以看到UsedHeap大约是UsedSize的一半,我找不到任何解释。

JVM退出并转储OutOfMemory的报告,您可以在这里找到:https://frojasg1.com/stackoverflow/20210423.OutOfMemory/hs_err_pid26210.log

这里是整个Java飞行记录仪报告:https://frojasg1.com/stackoverflow/20210423.outofmemory/test.7z

有没有人知道为什么会出现这种记忆?

共有1个答案

宰父淳
2023-03-14

日志文件是这样写的:

# Native memory allocation (mmap) failed to map 520093696 bytes 
for committing reserved memory.

所以发生的情况是,JVM通过mmap系统调用从OS请求了一个大约500MB的内存块,而OS拒绝了。

我能想到几个可能的原因:

>

  • 操作系统可能没有交换空间来支持内存分配。

    您的JVM可能已经达到了每个进程的内存限制。(在UNIX/Linux上,这是作为ulimit实现的。)

    如果您的JVM运行在Docker(或类似的)容器中,那么您可能已经超过了容器的内存限制。

    这不是一个“正常”OOME,不能通过改变Java堆的垃圾收集器选项来解决。必须在操作系统级别处理;例如取消或增加限制,或增加更多交换空间(或可能是RAM)。

  •  类似资料:
    • PS:有时我会从java代码执行shell脚本。会不会导致这类问题?

    • 我想检查我的应用程序是否很好地获得选项。 java进程在docker容器中运行。 为了做到这一点,我要找到所创建进程的最大堆大小。 null 假设(ngcmx+ogcmx)=()可以吗? https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html

    • 对于堆排序,如果我们想按升序对数组排序,那么应该在最大堆还是最小堆中转换堆?

    • 这里和这里都有类似的问题,但对JVM参数的更改都没有让我找到相同的解决方案。我只是想减少JVM未使用的堆大小,以便它更接近实际使用情况(将其释放给操作系统)。我一直在使用YourKit来分析内存使用情况,它通常如下所示: 我正在运行智能Ij IDEA社区版64位,在Windows 7 64位,8 GB RAM上运行。我已经编辑了.文件在这里找到: 与上述链接中提到的建议。第一个链接的答案实际上是错

    • 运行递归程序时遇到JavaStackOverFlowError。程序是正确的,需要实现递归。我尝试使用命令查找当前堆栈大小 这就是我得到的: Java版本"1.8.0_101"Java(TM)SE运行时环境(build 1.8.0_101-b13)JavaHotSpot(TM)64位服务器VM(build 25.101-b13,混合模式) 这是什么意思?如何增加堆栈大小以及应该设置什么值?对于上述

    • 我正在运行Apache Ignite应用程序。当我看到使用linux的内存使用时,我得到的使用内存为9.8GB。但是当我使用eclipse MAT进行堆转储时,它的大小只有大约1.8GB。为什么会这样?ignite中分配的默认堆内存为21 GB。我也没有做任何GC调优。