我有一台 Linux 服务器(Debian 10,16GB 物理内存),上面运行着三个 docker 容器和两个 Java 程序,用于执行财务计算。
Docker 容器:
所以没什么特别的。
Java 程序:
这些程序的启动方式如下。注意
-Xmx10g
参数:
./java/jdk/bin/java -Xmx10g -jar portal-backend-1.0-SNAPSHOT-runner.jar 2>&1 >> log/portal.log &
./java/jdk/bin/java -Xmx10g -jar pea-backend-1.0-SNAPSHOT-runner.jar 2>&1 >> log/pea.log &
交换文件:
我的 24GB 交换文件的配置:
fallocate -l 24G /swapfile
chown root:root /swapfile
sudo chmod 0600 /swapfile
格式化交换文件:
mkswap /swapfile
激活交换文件:
swapon /swapfile
在文件“/etc/fstab”中添加:
/swapfile swap swap defaults 0 0
当我现在输入
swapon -s
作为状态时,我收到以下消息:
Filename Type Size Used Priority
/swapfile file 25165820 0 -2
问题:
即使我激活了
SWAP file
,我还是得到了 out-of-memory exception
。有趣的是,SWAP 文件始终为 0KB。似乎永远不会受到攻击。怎么了?
在收到消息之前附上一张
htop
的照片Out-of-memory-Exception
//编辑
顺便说一句,我不明白为什么我在这个话题上得到负分
至少要回答你的问题,为什么你得到
OutOfMemoryError
,尽管你的交换文件没有被使用:
这两件事都要分开来看。您可以使用选项
-Xmx10g
指定 Java 进程使用的固定最大 RAM 量。您的 JVM 不会向操作系统请求更多堆内存,而是抛出您观察到的错误。
由于 JVM 需要的内存不仅仅是堆内存,您可以在
htop
屏幕截图中看到崩溃进程正在使用 13.9MB 的操作系统内存。这似乎是可行的,你可以观察一下。
因此,当实际上堆的过度使用成为问题时,您的程序中可能存在内存泄漏(例如,尽管您不需要它们的内容或类似内容,但从未清除的循环引用或集合)或者它必须处理一些非常大的内容数据块,但不准备以“流”方式(例如网络请求)这样做,而是尝试一次分配所有堆。
仅增加最大可用堆可能会暂时有所帮助,但如果要处理的输入数据很大,则下一个更大的块将再次使程序崩溃。
如果问题是内存泄漏,更大的堆空间可能会导致垃圾收集时间越来越长,并且您的程序在垃圾收集运行时将无法响应。
要摆脱这种崩溃,如果它只是“基于时间”或“基于输入”,您将必须进行更多调查。基于时间意味着运行一定时间后,程序通常会崩溃(如果在正常负载下)。 基于输入意味着特殊输入会触发崩溃(可能是大输入或触发特殊计算的输入)。