必须设--memory硬上限并禁用swap,因JVM默认感知宿主机内存而非容器限制,仅靠-Xmx等参数无法防止OOM Killer杀进程;需同步配置-XX:MaxDirectMemorySize、-XX:MaxMetaspaceSize和-Xss,并验证cgroup文件确认限制生效。

Java 应用容器化后,不设内存硬限制,极易因堆外内存增长(如 Direct Buffer、Metaspace、线程栈)或 GC 失效导致容器持续吃内存,最终触发宿主机 OOM Killer 杀进程,甚至拖垮整机。关键不是“配多少”,而是“怎么配才真正生效且不被 JVM 忽略”。
必须设 --memory 硬上限,禁用 swap 防掩盖问题
只靠 JVM 参数(如 -Xmx)完全不够——JVM 默认感知的是宿主机总内存,不是容器限制。比如宿主机有 32G,容器只分了 1G,但 JVM 若按 32G 自动设堆,很快就会超限被杀。
- 用 --memory=1g(或 -m 1g)强制划出物理内存红线,超限即终止主进程,不等待、不交换
- 同步加 --memory-swap=1g:让 swap 总量 = 物理内存,等于彻底禁用 swap,避免换页延迟暴露、掩盖内存泄漏
- 切勿只写 --memory=1g 却漏掉 --memory-swap——Docker 会默认补上等量 swap(即 1g RAM + 1g Swap),反而削弱保护效果
CPU 优先用 --cpus 做硬隔离,别依赖 cpu-shares
Java 应用常有突发 GC 或日志刷盘行为,若 CPU 无硬边界,可能抢占全部资源,影响其他服务响应。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 用 --cpus=1.5 直接限制最大可用逻辑 CPU 时间,底层对应 cgroups 的
cfs_quota_us / cfs_period_us,空闲和高负载下都稳定生效 - 避免仅用 --cpu-shares=512:它只是争抢时的权重比例,宿主机空闲时该容器仍可跑满所有核,无法防失控
- 对低延迟 Java 服务(如网关、实时计算),可追加 --cpuset-cpus=0-1 绑定特定核,减少跨核缓存抖动
Java 容器内存要留余量,JVM 堆必须小于 --memory
容器内存 ≠ JVM 堆内存。它还要容纳元空间、直接内存、线程栈、JIT 编译代码、容器运行时开销(约 10%~15%)。
立即学习“Java免费学习笔记(深入)”;
- 若容器设 --memory=1g,JVM 堆建议设 -Xmx768m,元空间加 -XX:MaxMetaspaceSize=256m,再预留缓冲
- 显式限制直接内存:-XX:MaxDirectMemorySize=256m,防止 Netty 或 NIO 框架无节制申请
- 控制线程数与栈大小:-Xss256k(而非默认 1M),尤其在高并发连接场景下能显著降低栈内存占用
验证配置是否落地,别信命令行,看 cgroup 文件
启动后光看 docker run 命令没用,得确认内核实际加载的限制值。
- 查内存硬限:
docker exec myjava cat /sys/fs/cgroup/memory/memory.limit_in_bytes→ 应输出1073741824(即 1G 字节) - 查 swap 总限:
docker exec myjava cat /sys/fs/cgroup/memory/memory.memsw.limit_in_bytes→ 应与上值相等,说明 swap 已禁用 - 查 CPU 配额:
docker exec myjava cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us和/sys/fs/cgroup/cpu/cpu.cfs_period_us→ 比值应等于你设的 --cpus 值(如 150000 / 100000 = 1.5)

















