java - 即使内存可用,JVM 也会崩溃并出现错误 ='Cannot allocate memory' (errno=12)

标签 java

我遇到 JVM 无法在 Java 中分配内存的问题

OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000000734880000, 880279552, 0) failed; error='Cannot allocate memory' (errno=12)

There is insufficient memory for the Java Runtime Environment to continue. Native memory allocation (mmap) failed to map 880279552 bytes for committing reserved memory. An error report file with more information is saved as: /home/ec2-user/tools/apache/apache-tomcat-9.0.6/bin/hs_err_pid23366.log java.lang.NullPointerException

这是我的内存统计数据

MemTotal:        8166744 kB
MemFree:         3788780 kB
MemAvailable:    3861816 kB
Buffers:               0 kB
Cached:           286536 kB
SwapCached:            0 kB
Active:          4030520 kB
Inactive:         182596 kB
Active(anon):    3926808 kB
Inactive(anon):    24892 kB
Active(file):     103712 kB
Inactive(file):   157704 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:               192 kB
Writeback:             0 kB
AnonPages:       3926652 kB
Mapped:            72652 kB
Shmem:             25120 kB
Slab:             100300 kB
SReclaimable:      60032 kB
SUnreclaim:        40268 kB
KernelStack:        5616 kB
PageTables:        21632 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     4083372 kB
Committed_AS:    5723980 kB
VmallocTotal:   34359738367 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      286720 kB
DirectMap2M:     8101888 kB

这可能看起来像是重复的 JVM 堆内存不足问题。最接近这个问题的是 this thread

但是,不同之处在于,在链接线程中,用户的可用空间较少,而 JVM 试图分配更高的内存(打开和关闭情况)。

在我的例子中,JVM 尝试分配 880279552 btes (0.8 GB),而我的可用内存(上图)为 3.7 GB。 JVM 尽管拥有近 4 倍的可用内存却无法分配它,这可能是什么原因?附带问题:为什么它要尝试分配 0.8 GB 内存。这是正常的吗?有没有办法通过工具更深入地找出此类分配?谁能指出一个资源来更好地理解上面的内存统计信息?

这是我在 setenv.sh 中的 JVM 配置(这是一台 8 GB RAM 的机器)

export CATALINA_HOME="/home/ec2-user/tools/apache/apache-tomcat-9.0.6/"
export JAVA_OPTS="-Xms2048m -Xmx4096m -DJDBC_CONNECTION_STRING=jdbc:mysql://localhost:3306/databasename?autoReconnect=true -DJDBC_DATABASER=dbname-DJDBC_USER=username-DJDBC_PASSWORD=password-DAPPLICATION_PRO$
export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-0.amzn2.x86_64"

崩溃后,这是内存消耗最高的服务,在 java 消耗 3.1 GB 后,MySQL 使用了 0.5 GB(再次确认第一个内存统计屏幕截图,其中显示 4 GB 内存是空闲/可用的)

  PID  PPID CMD                         %MEM %CPU
 4890     1 /usr/lib/jvm/java-1.8.0-ope 38.1  1.0
23204     1 /usr/sbin/mysqld --daemoniz  7.1  0.9
26056  3484 node /home/ec2-user/tools/j  1.3  111
 3548  3484 node /home/ec2-user/tools/j  1.1  0.3
 3484     1 PM2 v3.5.0: God Daemon (/ro  0.7  0.6
26067 26056 /root/.nvm/versions/node/v1  0.3  7.5
26074 26067 /root/.nvm/versions/node/v1  0.3  7.5
 3610  3548 /root/.nvm/versions/node/v1  0.3  0.0
 3624  3610 /root/.nvm/versions/node/v1  0.3  0.0

任何有助于理解这一点的帮助都将不胜感激。

最佳答案

@vlumi 和其他人试图引导我走向“没有可用的直接内存”的正确方向。尽管如此,我也开始遇到“堆内存不足”“内存不足”等其他问题。

问题如下:在tomcat服务器上重新部署WAR后,现有线程没有被杀死,它们的引用仍然存在,因此GC无法清理它。原始元空间(之前称为 PermGen)有 80MB,随着应用程序的运行,这个空间增长到 125MB。重新部署后,VisualVM 分析器上的元空间显示为 170MB,而不是返回到 80MB,在下一次重新部署中显示为 210。这清楚地表明,再进行十几次重新部署(这是测试服务器)后,JVM 将耗尽 RAM 空间分配并抛出堆内存。

为了解决这个问题,我们在 Jenkins 作业中添加了 tomcat7:shutdown (或通过 shell 脚本重新启动)。停止和启动 tomcat 能够像以前一样默认返回到元空间。其他一些人试图杀死 jama 进程,以便杀死所有线程。

感谢大家的贡献。这是link访问最有助于了解实际情况的网站。

关于java - 即使内存可用,JVM 也会崩溃并出现错误 ='Cannot allocate memory' (errno=12),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57040639/

相关文章:

java - Drools 操作对象成员变量未设置

java - 适用于 Windows 7(x32) 的 Gdal

java - 基本Java环境问题:

java - 添加将 JPanel 扩展为 JFrame 的公共(public)类

c# - 来自 C# 背景的哪个更容易学习 : Objective C or Java?

java - BIRT - 我应该将图像放在哪里,以便可以预览并部署到 Web 应用程序中

java - 如何将我的 NetBeans 项目加载到 sonarqube 中?

java - 单选按钮 setChecked NullPointerException

java - 哪种递归方法更好?为什么对于整数的反转数字?

java - Android SQLite 行不更新