我写了一个简短的Java程序来分配内存:
package com.company;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static final int SIZE_NATIVE_LONG_IN_BYTE = 8;
public static void main(String[] args) {
Integer memoryConsumptionInMiB = Integer.parseInt(args[0]);
List<long[][]> foo = new ArrayList<long[][]>();
int i = 0;
while (true) {
System.out.println(i++);
foo.add(new long[(1024 / SIZE_NATIVE_LONG_IN_BYTE * 1024)][memoryConsumptionInMiB]);
}
}
}
我尝试在Docker容器中使用不同的参数运行它:
- 使用Xmx 1G和没有内存限制的Docker容器
- 使用Xmx 1G和docker run -m 512m
- 使用Xmx 1G和docker run -m 512m --disable-oom-killer
(编辑:上传了一个包含上述类的预先准备好的镜像)
docker run -it --oom-kill-disable -m 512m kazesberger/alpine-java-memory-tester java -classpath . com.company.Main 10 (~Megabytes allocated per iteration)
我的期望是:
- 堆内存超过 1G 时出现 OutOfMemory 错误。
- 在真正发生 OutOfMemory 错误之前,主机操作系统会杀死 Docker 容器(可以通过 docker inspect 或内核日志来证明)。
- Docker 容器中的 malloc 失败,导致 jvm 终止并出现某种 OutOfMemoryError。
实际结果为:
- 期望达成。
- 期望达成。
- oomkiller 仍然杀死容器。docker inspect 仍然显示 OOMKilled 为 true。
因此,你可以看到我的真正目标并不是抑制 oomKiller 实现其功能。相反,我的目标是使容器内的进程在分配未授权内存时失败。
前提条件/版本信息:
swapoff -a
docker --version Docker version 17.11.0-ce-rc4, build 587f1f0
docker run -it kazesberger/alpine-java-memory-tester java -version openjdk version "1.8.0_111-internal"