我正在尝试强制执行程序在 Unix 系统上可以消耗的最大内存。我认为 ulimit -v 应该可以解决问题。这是我为测试编写的一个示例 Java 程序:
import java.util.*;
import java.io.*;
public class EatMem {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("Starting up...");
System.out.println("Allocating 128 MB of Memory");
List<byte[]> list = new LinkedList<byte[]>();
list.add(new byte[134217728]); //128 MB
System.out.println("Done....");
}
}
默认情况下,我的 ulimit 设置是(ulimit -a 的输出):
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31398
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 31398
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
当我执行 Java 程序 (java EatMem) 时,它执行没有任何问题。现在我尝试通过启动以下命令将当前 shell 中启动的任何程序的最大可用内存限制为 512MB:
ulimit -v 524288
ulimit -a 输出显示限制设置正确(我认为):
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31398
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 31398
virtual memory (kbytes, -v) 524288
file locks (-x) unlimited
如果我现在尝试执行我的 java 程序,它会给出以下错误:
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
理想情况下,这种情况不应该发生,因为我的 Java 程序仅占用大约 128MB 的内存,这完全在我指定的 ulimit 参数之内。如果我将 Java 程序的参数更改为如下形式:
java -Xmx256m EatMem
该程序再次正常运行。尝试提供比 ulimit 限制更多的内存时,例如:
java -Xmx800m EatMem
导致预期的错误。为什么设置 ulimit 后,程序在第一种情况下执行失败?
我已经在 Ubuntu 11.10 和 12.0.4 上使用 Java 1.6 和 Java 7 进行了上述测试
答案1
ulimit -v
设置程序可以使用的最大地址空间。这包括所有共享内存,如库、线程堆栈空间、直接内存等。由于 JVM 并非设计为在这种有限的虚拟内存环境中运行,因此它可能无法以最佳方式布局。也就是说,因为虚拟内存通常非常非常便宜。我怀疑您必须将此值设置得更高才能使 JVM 运行。
顺便说一句:JVM 在启动时分配最大堆大小。
如果我决定ulimit -v 524288
并尝试做
运行正常
java -mx64m -version
java -mx128m -version
java -mx256m -version
由于 malloc 失败而崩溃
java -mx300m -version
VM 初始化过程中发生错误
java -mx400m -version
java -mx512m -version
这或多或少是预期的行为。