限制Java 8内存消耗

时间:2017-12-13 12:30:12

标签: jvm-arguments jvm-hotspot

我在64位Ubuntu VM上运行了三个Java 8 JVM,它是通过最小安装构建的,除了三个JVM之外没有任何额外的运行。 VM本身有2GB的内存,每个JVM都受-Xmx512M的限制,我认为这样会很好,因为有几百MB的备用。

几个星期前,一个崩溃,hs_err_pid转储显示:

# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 196608 bytes for committing reserved memory.
# Possible reasons:
#   The system is out of physical RAM or swap space
#   In 32 bit mode, the process size limit was hit
# Possible solutions:
#   Reduce memory load on the system
#   Increase physical memory or swap space
#   Check if swap backing store is full
#   Use 64 bit Java on a 64 bit OS
#   Decrease Java heap size (-Xmx/-Xms)
#   Decrease number of Java threads
#   Decrease Java thread stack sizes (-Xss)
#   Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.

我重新启动了JVM,堆大小减少了384MB,到目前为止一切都很好。但是,当我目前使用ps命令查看VM并按RSS大小降序排序时,我看到

RSS %MEM    VSZ   PID CMD
708768 35.4 2536124 29568 java -Xms64m -Xmx512m ...
542776 27.1 2340996 12934 java -Xms64m -Xmx384m ...
387336 19.3 2542336 6788 java -Xms64m -Xmx512m ...
12128  0.6 288120  1239 /usr/lib/snapd/snapd
 4564  0.2  21476 27132 -bash
 3524  0.1   5724  1235 /sbin/iscsid
 3184  0.1  37928     1 /sbin/init
 3032  0.1  27772 28829 ps ax -o rss,pmem,vsz,pid,cmd --sort -rss
 3020  0.1 652988  1308 /usr/bin/lxcfs /var/lib/lxcfs/
 2936  0.1 274596  1237 /usr/lib/accountsservice/accounts-daemon
..
..

,免费命令显示

              total        used        free      shared  buff/cache   available
Mem:           1952        1657          80          20         213          41
Swap:             0           0           0

以第一个进程为例,即使堆限制为524288 KB(512 * 1024),RSS大小仍为708768 KB。

我知道在JVM堆上使用了额外的内存,但问题是如何控制它以确保我不会再次耗尽内存?我试图尽可能大地为每个JVM设置堆大小而不会崩溃它们。

或者是否有关于如何根据总体内存可用性设置JVM堆大小的一般指南?

1 个答案:

答案 0 :(得分:0)

似乎没有办法控制JVM在堆上使用多少额外内存。但是,通过在一段时间内监控应用程序,可以获得对该数量的良好估计。如果java进程的总体消耗高于期望值,则可以减小堆大小。需要进一步监测以确定这是否会影响绩效。

继续上面的示例并使用命令 ps ax -o rss,pmem,vsz,pid,cmd --sort -rss ,我们看到今天的用法是

  RSS %MEM    VSZ   PID CMD
704144 35.2 2536124 29568 java -Xms64m -Xmx512m ...
429504 21.4 2340996 12934 java -Xms64m -Xmx384m ...
367732 18.3 2542336 6788 java -Xms64m -Xmx512m ... 
13872  0.6 288120  1239 /usr/lib/snapd/snapd
..
..

这些java进程都运行相同的应用程序但具有不同的数据集。第一个过程(29568)使用超过堆限制约190M保持稳定,而第二个过程(12934)从156M减少到35M。第三个的总内存使用量保持在堆大小之下,这表明可以减少堆限制。

似乎每个java进程允许200MB额外的非堆内存就足够了,因为它总共有600MB的余地。从2GB减去1400MB,因此三个 -Xmx 参数值的总和应该小于这个数量。

从阅读Fairoz评论中指出的文章中可以看出,JVM可以使用非堆内存的方式有很多种。其中一个可测量的是线程堆栈大小。可以使用 java -XX在Linux上找到JVM的默认值:+ PrintFlagsFinal -version | grep ThreadStackSize 在上面的情况下,它是1MB,因为大约有25个线程,我们可以肯定地说,总是需要至少25MB的额外费用。