在Ubuntu上限制JVM进程的内存使用

11

我知道有很多类似这个问题已经有了回答,但我对这些回答感到不满意,所以我在这里详细描述一下。

我尝试使用JVM OPTs启动我的应用程序:-Xmx128m -Xms32m -XX:MaxPermSize=64m。当应用程序启动后,我通过输入cat /proc/10413/status来检查内存使用情况,发现vmsize超过了600512 kB!这比我的设置要大得多。我想知道如何限制进程的jvm内存使用。

Name:   java
State:  S (sleeping)
Tgid:   10413
Pid:    10413
PPid:   1
TracerPid:      0
Uid:    1001    1001    1001    1001
Gid:    1007    1007    1007    1007
FDSize: 128
Groups: 1001 1007
**VmPeak:   728472 kB**
**VmSize:   600512 kB**
VmLck:         0 kB
VmHWM:    298300 kB
VmRSS:    280912 kB
VmData:   647804 kB
VmStk:       140 kB
VmExe:        36 kB
VmLib:     13404 kB
VmPTE:       808 kB
VmSwap:        0 kB
Threads:        33
SigQ:   0/31522
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 2000000181005ccf
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed:   f
Cpus_allowed_list:      0-3
Mems_allowed:   00000000,00000001
Mems_allowed_list:      0
voluntary_ctxt_switches:        3
nonvoluntary_ctxt_switches:     2
2个回答

11

你无法控制想要控制的东西-Xmx 只能控制 Java Heap,它不能控制 JVM 消耗的本机内存,因为这取决于实现方式。

引自以下文章Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )

维护堆和垃圾收集器使用本机内存,您无法控制。

维护 Java 堆的内存管理系统状态需要更多本机内存。必须分配数据结构来跟踪空闲存储并记录垃圾回收进度。这些数据结构的确切大小和性质因实现而异,但许多与堆的大小成比例。

JIT 编译器像 javac 一样使用本机内存。

字节码编译使用本地内存(就像静态编译器如gcc需要内存运行一样),但JIT的输入(字节码)和输出(可执行代码)也必须存储在本地内存中。包含许多JIT编译方法的Java应用程序比较小的应用程序使用更多的本地内存。
然后您有使用本地内存的类加载器。
Java应用程序由定义对象结构和方法逻辑的类组成。它们还使用Java运行时类库(例如java.lang.String)中的类,并可能使用第三方库。只要使用这些类,它们就需要存储在内存中。类的存储方式因实现而异。
我甚至不会开始引用线程部分,我想您已经明白了-Xmx并不控制您认为它控制的内容,它控制JVM堆,不是所有内容都放在JVM堆中,堆占用的本地内存比您指定的管理和簿记要多得多。

1

像 Linux 上的任何其他进程一样,您可以限制 JVM 进程的内存使用量(例如限制为 4 GB):

$ ulimit -v 4194304
$ java ...   # execute your Java program

(从技术上讲,这实际上是虚拟内存,是实际内存使用的上限。但是ulimit 显然不能用于实际的RAM使用。

这会导致超过限制的内存分配失败,可能会导致OutOfMemoryError和您的应用程序退出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接