即使内存可用,JVM也会因错误=“无法分配内存”(errno = 12)而崩溃

时间:2019-07-15 13:19:47

标签: java

我遇到了JVM无法用Java分配内存的问题

  

OpenJDK 64位服务器VM警告:INFO:   os :: commit_memory(0x0000000734880000,880279552,0)失败;   error ='无法分配内存'(errno = 12)

     

没有足够的内存供Java Runtime Environment使用   继续。本机内存分配(mmap)无法映射880279552   用于提交保留内存的字节。错误报告文件,其中包含更多内容   信息另存为:   /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(这是8 GB RAM计算机)中的JVM配置

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

感谢您帮助我们理解这一点。

1 个答案:

答案 0 :(得分:1)

@vlumi和其他人试图以“没有可用的直接内存”的正确方向指导我。但是,我还开始遇到“堆内存不足”和“内存不足”的其他问题。

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

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

感谢大家的贡献。这是该网站的link,对您最了解实际情况的帮助最大。