你会经常遇到这种需求“这个服务要配多大堆”“为什么 GC 抖动是不是堆太小”“线上 OOM 了先把-Xmx调大行不行”很多人上来就背-Xms/-Xmx但更靠谱的工程做法是先建立内存基线再决定参数。1. 你要先分清堆变大不等于问题消失把堆调大可能带来的后果Full GC 一次更久停顿更长如果是泄露调大只是“延迟爆炸时间”你把机器内存吃满可能把 OS/别的进程拖死所以这篇的目标是让你知道“堆参数控制的是什么”让你有一套可执行的“设置 - 验证 - 观察”闭环2. 堆大小的核心参数-Xms/-Xmx-Xms初始堆大小-Xmx最大堆大小工程上常见做法-Xms与-Xmx设成一样原因避免运行期堆扩容带来的抖动避免你以为“堆够了”实际上只是还没涨到Xmx3. 新生代/老年代怎么配先理解目标再谈参数不同收集器参数不完全一样但你要知道这个关系新生代短命对象多Minor GC 频繁老年代长寿对象多Major/Old GC 成本更高你通常想要Minor GC 更快新生代回收成本低Old GC 更少老年代不要太快被打满常见参数以 HotSpot 常见语境理解即可具体以你使用的收集器/版本为准-XX:NewRatio老年代与新生代比例-Xmn新生代大小有时也会用注意不建议在没有指标的情况下硬调很多细项优先“堆总量 收集器选择 GC 日志”三件套4. 直接把“你该怎么配”的方法讲清楚内存基线法4.1 建基线业务稳定期的内存曲线你需要回答两个问题稳态时堆使用大概是多少峰值时堆使用最高会到多少4.2 给出安全余量经验上至少留业务峰值对象 缓存波动 突发流量的余量4.3 再决定-XmxXmx不是越大越好你要考虑容器/机器总内存其他进程占用OS Page Cache5. 如何验证你当前服务的堆配置与实时占用实战命令5.1 看启动参数jcmd pid VM.command_line5.2 看堆结构与各代使用jcmd pid GC.heap_info5.3 如果你有 GC 日志用它确认“抖动来源”你至少要能从 GC 日志看懂Minor GC 是否过于频繁Old GC/Full GC 是否出现STW 时间是否超过你的业务容忍6. 常见问题堆参数怎么和容器内存配合如果你跑在容器里关注容器的内存限制不要让 JVM 把容器内存当成“机器总内存”一般建议给 JVM 留出一部分非堆内存空间线程栈、元空间、直接内存等Xmx不要顶满容器上限7. JDK 1.7 与 JDK 1.8别把堆和方法区混了你会看到两种 OOMOutOfMemoryError: Java heap space堆OutOfMemoryError: PermGen spaceJDK 1.7 常见永久代OutOfMemoryError: MetaspaceJDK 1.8 常见元空间结论PermGen/Metaspace不是堆不要只调-Xmx8. 总结你可以照着做的最小闭环先用业务稳定期/峰值期建立内存基线再决定-Xmx并预留非堆空间用jcmd VM.command_lineGC.heap_info验证若出现抖动/GC 问题下一步看 GC 日志或做 heapdump
JVM 堆参数怎么设:先建立内存基线,再谈性能优化
你会经常遇到这种需求“这个服务要配多大堆”“为什么 GC 抖动是不是堆太小”“线上 OOM 了先把-Xmx调大行不行”很多人上来就背-Xms/-Xmx但更靠谱的工程做法是先建立内存基线再决定参数。1. 你要先分清堆变大不等于问题消失把堆调大可能带来的后果Full GC 一次更久停顿更长如果是泄露调大只是“延迟爆炸时间”你把机器内存吃满可能把 OS/别的进程拖死所以这篇的目标是让你知道“堆参数控制的是什么”让你有一套可执行的“设置 - 验证 - 观察”闭环2. 堆大小的核心参数-Xms/-Xmx-Xms初始堆大小-Xmx最大堆大小工程上常见做法-Xms与-Xmx设成一样原因避免运行期堆扩容带来的抖动避免你以为“堆够了”实际上只是还没涨到Xmx3. 新生代/老年代怎么配先理解目标再谈参数不同收集器参数不完全一样但你要知道这个关系新生代短命对象多Minor GC 频繁老年代长寿对象多Major/Old GC 成本更高你通常想要Minor GC 更快新生代回收成本低Old GC 更少老年代不要太快被打满常见参数以 HotSpot 常见语境理解即可具体以你使用的收集器/版本为准-XX:NewRatio老年代与新生代比例-Xmn新生代大小有时也会用注意不建议在没有指标的情况下硬调很多细项优先“堆总量 收集器选择 GC 日志”三件套4. 直接把“你该怎么配”的方法讲清楚内存基线法4.1 建基线业务稳定期的内存曲线你需要回答两个问题稳态时堆使用大概是多少峰值时堆使用最高会到多少4.2 给出安全余量经验上至少留业务峰值对象 缓存波动 突发流量的余量4.3 再决定-XmxXmx不是越大越好你要考虑容器/机器总内存其他进程占用OS Page Cache5. 如何验证你当前服务的堆配置与实时占用实战命令5.1 看启动参数jcmd pid VM.command_line5.2 看堆结构与各代使用jcmd pid GC.heap_info5.3 如果你有 GC 日志用它确认“抖动来源”你至少要能从 GC 日志看懂Minor GC 是否过于频繁Old GC/Full GC 是否出现STW 时间是否超过你的业务容忍6. 常见问题堆参数怎么和容器内存配合如果你跑在容器里关注容器的内存限制不要让 JVM 把容器内存当成“机器总内存”一般建议给 JVM 留出一部分非堆内存空间线程栈、元空间、直接内存等Xmx不要顶满容器上限7. JDK 1.7 与 JDK 1.8别把堆和方法区混了你会看到两种 OOMOutOfMemoryError: Java heap space堆OutOfMemoryError: PermGen spaceJDK 1.7 常见永久代OutOfMemoryError: MetaspaceJDK 1.8 常见元空间结论PermGen/Metaspace不是堆不要只调-Xmx8. 总结你可以照着做的最小闭环先用业务稳定期/峰值期建立内存基线再决定-Xmx并预留非堆空间用jcmd VM.command_lineGC.heap_info验证若出现抖动/GC 问题下一步看 GC 日志或做 heapdump