JVM 运行时五大内存分区分类、存储内容与对应异常

内存分区两大分类标准(线程私有 / 线程共享)
JVM 运行时数据区分为两类,核心区别:是否每个线程独立拥有内存、是否容易产生 OOM
- 线程私有(单线程独占,线程销毁内存直接释放,OOM 概率低)
- 程序计数器 PC Register
- 虚拟机栈 JVM Stack
- 本地方法栈 Native Method Stack
- 线程共享(整个进程共用,进程关闭才释放内存,高频出现 OOM)
- 堆 Heap(GC 主要回收区域)
- 方法区 Method Area(JDK8 后为元空间 Metaspace)

OutOfMemoryError内存溢出
JVM 运行程序时,需要分配一块内存存放对象、类、缓冲区等,但没有足够空闲内存满足本次分配需求,虚拟机直接抛出 OOM 异常,严重时服务进程崩溃。
和 StackOverflowError 区分
- StackOverflowError:栈深度超限,递归死循环、方法嵌套太多;栈空间本身是够的,只是层数放不下。
- OOM:整块内存容量耗尽,分配新内存失败。
五种常见 OOM 类型
-
Java heap space堆内存溢出。new 的对象、数组太多,GC 回收后依然没有空闲空间。 场景:内存泄漏、无限创建对象、超大集合缓存数据。 -
Metaspace元空间溢出。大量动态生成类:CGLIB 代理、频繁反射、热加载、动态脚本。 -
Direct buffer memory堆外直接内存溢出。NIO 读写文件 / 网络,DirectByteBuffer 堆外内存没手动释放。 -
虚拟机栈 OOM 栈支持动态扩容,操作系统无剩余内存分配新栈帧,极少出现。
-
本地方法栈 OOM native 方法申请本地内存耗尽,线上几乎遇不到。
OOM 根本两大诱因
- 内存参数设置过小:-Xmx 堆最大值、元空间上限配置太低;
- 代码内存泄漏:无用对象被强引用持续持有,GC 永远无法回收,内存慢慢占满。
私有三区:计数器、虚拟机栈、本地方法栈,随线程销毁;
共享两区:堆、元空间,全局共用易 OOM;
堆存对象、元空间存类信息,栈只存引用不存实体对象。
五大内存区域逐点详解
| 内存区域 | 线程归属 | 存储内容 | 内存回收方式 | 对应异常 | 调优参数 |
|---|---|---|---|---|---|
| 程序计数器 | 线程私有 | 当前线程执行的字节码指令地址 | 线程销毁自动释放 | 无 OOM(唯一不会溢出) | 无 |
| 虚拟机栈 | 线程私有 | 栈帧:局部变量表、操作数栈、动态链接、方法出口;存放基本类型、对象引用地址 | 方法执行完栈帧自动出栈,无 GC 参与 | StackOverflowError(栈深度超限)/ 栈 OOM(扩容失败) | -Xss(单个栈大小) |
| 本地方法栈 | 线程私有 | native 底层 C/C++ 方法栈帧 | 方法执行完自动释放 | StackOverflowError / 栈 OOM | -Xss |
| 堆 Heap | 线程共享 | 所有 new 创建的对象实例、数组实体;细分为新生代(Eden、S0、S1)、老年代 | GC 垃圾回收自动清理无用对象 | java.lang.OutOfMemoryError: Java heap space | -Xms(初始堆)/-Xmx(最大堆) |
| 方法区(元空间) | 线程共享 | 类字节码、静态变量、运行时常量池、类 / 方法 / 字段描述信息 | Full GC 时回收废弃类、常量 | java.lang.OutOfMemoryError: Metaspace | -XX:MaxMetaspaceSize |
程序计数器(PC 寄存器)
- 归属:线程私有
- 核心作用:记录当前线程执行到的字节码行号;多线程切换时,依靠该记录恢复执行位置
- 存储内容:字节码指令地址
- 异常特性:JVM 规范唯一不会发生 OOM 的内存区域
虚拟机栈(Java 栈)
- 归属:线程私有
- 存储载体:栈帧,每调用一个方法就创建一个栈帧,方法执行完毕栈帧出栈销毁
- 栈帧内部组成:局部变量表、操作数栈、动态链接、方法出口
- 存储数据:方法内局部基本数据类型、对象引用地址
- 抛出两类异常:
- StackOverflowError:递归死循环、多层方法嵌套,栈深度超出最大限制
- OutOfMemoryError:虚拟机栈支持动态扩容,系统剩余内存不足无法分配新栈帧
本地方法栈
- 归属:线程私有
- 作用:专门执行 native 本地方法(底层 C/C++ 系统调用、IO 操作等)
- 结构、异常类型和虚拟机栈完全一致,同样会栈溢出、内存溢出
堆 Heap(重点)
- 归属:线程共享,整个 JVM 最大内存区域,GC 核心回收区
- 存储内容:所有 new 关键字创建的对象实例、数组实体
- 堆内存细分:新生代(Eden 区、Survivor0、Survivor1)、老年代 Old 区
- 溢出异常:
java.lang.OutOfMemoryError: Java heap space触发场景:对象过多、大对象、内存泄漏,堆内存分配不足
方法区(JDK8 元空间 Metaspace)
- 归属:线程共享
- 版本变化:JDK1.7 及之前永久代 PermGen;JDK1.8 彻底移除永久代,使用堆外本地内存元空间
- 存储内容:类字节码文件、静态变量、运行时常量池、方法 / 字段描述、接口信息
- 溢出异常:
java.lang.OutOfMemoryError: Metaspace触发场景:大量动态代理 CGLIB、频繁反射、动态生成类

补充知识点:堆外直接内存 Direct Buffer(高频 OOM )
- 不属于五大运行时内存区,但线上极易溢出
- 来源:NIO 的 DirectByteBuffer,读写文件、网络 IO 使用堆外内存
- 限制:不受 - Xmx 堆内存参数管控
- 溢出异常:
java.lang.OutOfMemoryError: Direct buffer memory
虚拟机栈与堆内存核心对比表
| 对比维度 | 虚拟机栈 | 堆内存 |
|---|---|---|
| 线程归属 | 线程私有 | 线程共享 |
| 存储数据 | 局部变量、基本类型、对象引用地址 | new 创建的对象、数组实体 |
| 内存回收机制 | 方法执行完自动释放,无 GC 参与 | 依靠 GC 垃圾回收清理无用对象 |
| 溢出类型 | StackOverflowError、栈 OOM | Java heap space 堆内存溢出 |
| 内存参数控制 | -Xss 控制单个栈大小 | -Xms/-Xmx 控制堆初始 / 最大内存 |
| 生命周期 | 跟随线程,线程销毁栈直接释放 | 跟随进程,GC 持续回收闲置对象 |
判断对象存活的两种算法(引用计数、可达性分析 GC Roots)
| 判断算法 | 实现逻辑 | 优点 | 致命缺点 | JVM 是否使用 |
|---|---|---|---|---|
| 引用计数 | 对象自带计数器,引用 ±1,0 则回收 | 逻辑简单,实时回收 | 循环引用无法回收,内存泄漏 | 不使用 |
| 可达性分析 GC Roots | 从根对象遍历引用链,不可达为垃圾 | 解决循环引用,回收准确 | 需要扫描全堆,产生 STW 停顿 | HotSpot 默认,全行业通用 |
引用计数算法(已淘汰,仅理论了解)
核心原理
给每一个 Java 对象单独维护一个整型引用计数器:
- 当有变量引用该对象,计数器
+1; - 引用失效(变量销毁、重新赋值),计数器
-1; - 计数器数值为 0,判定为垃圾对象,可被 GC 回收。
致命缺陷(无法商用)
循环引用问题 两个对象 A、B,A 内部持有 B 的引用,B 内部持有 A 的引用;外部无任何变量指向 A 和 B。 此时两者计数器都不为 0,GC 永远识别不了这是垃圾,无法回收,长期堆积造成内存泄漏、堆 OOM。
结论
HotSpot 虚拟机完全放弃该算法。
可达性分析算法(HotSpot 虚拟机默认,生产主流)
核心逻辑
定义一系列GC Roots 根对象作为起点,从根向下遍历整个引用链:
- 遍历过程中能够访问到的对象 = 存活对象;
- 从 GC Roots 出发无法遍历到达的对象 = 垃圾对象,等待 GC 回收;
- 完美解决循环引用的痛点。
五类标准 GC Roots
- 虚拟机栈中局部变量引用的对象(方法内创建的对象);
- 方法区中静态变量、常量引用的对象(static 全局集合、常量对象);
- 本地方法栈 native 方法引用的底层对象;
- 同步锁 synchronized 持有的 monitor 锁对象;
- Java 系统内置对象:主线程、类加载器、系统 Class 等。
可达性分析完整执行流程

- 第一步:找到全部 GC Roots 收集虚拟机栈、静态变量、native 方法、锁、系统线程等根对象。
- 第二步:遍历引用链 以 GC Roots 为起点顺着对象引用一路遍历,沿途接触到的全部标记存活。
- 第三步:区分存活 / 垃圾 能走到 = 存活;完全走不到、无任何根可达 = 垃圾对象。
- 第四步:回收垃圾 根据 GC 算法(复制 / 标记清除 / 标记整理)清理垃圾,释放堆内存。
- 核心优势:即使两个对象互相循环引用,只要 GC Roots 碰不到,照样判定垃圾回收,解决引用计数致命问题。
对象四大引用类型
- 强引用 :
Object o = new Object()只要存在强引用,GC 永远不会回收,日常代码默认使用,静态集合极易靠强引用造成内存泄漏。 - 软引用 SoftReference 内存充足不回收,堆空间即将溢出时才回收;适合做缓存。
- 弱引用 WeakReference 只要发生 GC,无论内存是否充足都会被回收;缓存、临时映射场景使用。
- 虚引用 PhantomReference 无法通过引用获取对象,仅用于监控对象被回收的通知,极少业务使用。
| 引用类型 | 定义说明 | GC 回收时机 | 常见使用场景 | JDK 对应类 | 举例说明 |
|---|---|---|---|---|---|
| 强引用 | 普通new对象赋值给变量,默认就是强引用 |
只要强引用存在,GC永远不会回收;即使 OOM 也不回收 | 日常业务代码默认使用,绝大部分对象都是强引用 | 无特殊类,默认即强引用 | Object obj = new Object() |
| 软引用 SoftReference | 用 SoftReference 包装对象,内存充足时保留 | 内存充足时不回收;堆内存即将 OOM 溢出时才回收 | 内存敏感型缓存:图片缓存、大对象缓存 | java.lang.ref.SoftReference |
浏览器图片缓存,内存够就留着,不够就清掉 |
| 弱引用 WeakReference | 用 WeakReference 包装对象,生命周期比软引用更短 | 只要发生 GC,无论内存是否充足,都会被回收 | 临时映射、ThreadLocal、缓存、避免内存泄漏 | java.lang.ref.WeakReference |
ThreadLocal 的 key 就是弱引用,防止 ThreadLocal 内存泄漏 |
| 虚引用 PhantomReference | 最弱的引用,完全不影响对象生命周期,无法通过引用获取对象 | 对象被回收时收到通知,仅用于监控对象回收 | 堆外内存回收跟踪、NIO DirectByteBuffer 回收监控 | java.lang.ref.PhantomReference |
监控堆外直接内存释放,避免 DirectBuffer 泄漏 |
强引用:默认就是,永不回收,OOM 也不丢; 软引用:内存不够才回收,适合做大缓存;
弱引用:遇到 GC 就回收,适合临时映射; 虚引用:拿不到对象,只用来监控回收通知。
四大基础 GC 垃圾回收算法(原理、优缺点、适用区域)
标记 - 清除算法 Mark-Sweep
执行流程
- 标记阶段:从 GC Roots 遍历堆,把所有存活对象打上标记;
- 清除阶段:扫描整个堆,直接释放所有未标记的垃圾对象内存。
优点
实现逻辑简单,不需要移动任何存活对象。
缺点
- 回收完成后产生大量不连续内存碎片;分配大对象时找不到连续空间,频繁触发 Full GC;
- 需要两次完整遍历堆内存,GC 效率偏低。
适用场景
仅老年代简易回收场景,生产环境不会单独使用。
复制算法 Copying
执行流程
将内存划分为两块同等大小区域 A、B;
- 平时只使用 A 区存放新对象;
- GC 触发时,把 A 区内所有存活对象复制到空白 B 区,保证内存连续;
- 复制完成后直接清空 A 区,交换 A、B 角色,下一次 GC 复用。
优点
- 复制后内存完全连续,无内存碎片;
- 分配对象速度快,仅移动指针即可分配。
缺点
- 永久浪费一半堆内存空间;
- 存活对象数量多时,复制成本极高,停顿时间变长。
适用场景
新生代(Eden+Survivor),新生代大部分对象朝生夕死,存活对象极少,复制开销很低。
标记 - 整理算法 Mark-Compact
执行流程
- 标记阶段:同标记清除,标记全部存活对象;
- 整理阶段:将所有存活对象向内存一端压缩、移动,全部紧凑排列;
- 边界以外整块空间全部清空,形成连续空闲内存。
优点
回收后无内存碎片,空闲内存连续,适合存放大对象。
缺点
需要大量移动存活对象,STW 停顿时间很长,性能损耗大。
适用场景
老年代(老年代存活对象多,复制算法浪费一半内存,不适合)。
分代收集算法 Generational Collection(商用主流组合算法)

核心思想
根据对象存活生命周期把堆分为新生代、老年代,不同分代匹配最优回收算法:
- 新生代:对象生命周期短、存活少 → 复制算法;
- 老年代:对象长期存活、数量多 → 标记清除 / 标记整理。
业务执行流程
- 新创建对象分配在 Eden 区;
- Eden 占满触发 Minor GC,存活对象复制到 Survivor;
- 多次 GC 仍存活的对象晋升到老年代;
- 老年代空间不足,触发 Full GC,使用标记整理回收。

优点
结合复制、标记整理两者优势,综合性能最优,所有商用回收器(Parallel GC、CMS、G1、ZGC)底层均基于分代收集。
缺点
需要维护两套回收逻辑,虚拟机底层实现复杂。
| GC 算法 | 核心流程 | 优点 | 缺点 | 适用内存区域 |
|---|---|---|---|---|
| 标记清除 | 标记存活对象,直接清理垃圾 | 实现简单,无需移动对象 | 产生大量内存碎片,两次全堆遍历效率低 | 老年代简易场景,不单独生产使用 |
| 复制 | 存活对象复制到备用分区,清空原分区 | 无内存碎片,对象分配速度快 | 永久浪费 50% 内存,存活多复制开销大 | 新生代 Eden/Survivor |
| 标记整理 | 标记存活,全部向一端压缩移动 | 无内存碎片,空闲空间连续 | 大量移动对象,STW 停顿时间长 | 老年代 |
| 分代收集 | 新生代复制、老年代标记整理组合使用 | 分代适配,综合性能最优 | 多代逻辑管理复杂 | 完整堆内存,线上通用标准 |
高并发营销场景完整 JVM 内存 & GC 串联实战流程
业务场景描述
营销大促,大量用户同时领取优惠券、下单,循环创建优惠券 DTO、订单临时对象。
对象分配与 GC 完整流程
- 用户并发请求,代码执行 new 创建大量临时对象,全部分配到新生代 Eden 区;
- Eden 区快速被占满,触发 Minor GC;
- 大部分一次性临时请求对象无外部引用,直接被回收;少量缓存、待支付订单存活对象,通过复制算法转移到 Survivor 区;
- 存活对象每经历一次 Minor GC,年龄 + 1;多次 GC 后仍存活的长期缓存对象(优惠券活动缓存、用户基础信息),达到年龄阈值晋升到老年代;
- 若代码存在全局静态 Map 无限存入用户数据,老年代对象持续增长;
- 老年代剩余空间不足以容纳新晋升对象,触发 Full GC,采用标记整理算法压缩回收无效老年代对象;
- 若堆内存参数配置过小,Full GC 后依然没有连续空闲内存分配对象,抛出
Java heap spaceOOM,服务宕机; - 代码大量使用 CGLIB 动态代理、反射生成类,类字节码持续填充元空间,最终触发 Metaspace 元空间溢出 OOM。
该场景下会出现的两类线上故障
故障 1:频繁 Minor GC,接口轻微卡顿
- 现象:接口响应变慢,无大量报错,GC 日志 Minor GC 频率极高
- 根因:循环内不停 new 临时大对象、未复用实体 DTO,Eden 快速填满
- 优化:对象池复用对象、缩小方法外对象生命周期、调大新生代 Xmn 参数
故障 2:频繁 Full GC,CPU 打满、大量接口超时
- 现象:CPU 持续 100%,大量请求超时,日志频繁打印 Full GC
- 根因:全局静态集合内存泄漏、大对象直接进入老年代、堆内存配置不足
- 应急方案:导出 dump 文件,MAT 工具分析内存占用;临时调大 - Xmx 堆内存;业务低峰期修复内存泄漏代码
短期临时对象 → 新生代 + Minor GC(复制算法)
长期缓存静态对象 → 老年代 + Full GC(标记整理)
动态生成代理类 / 反射 → 元空间溢出 OOM
线上 JVM 内存 / GC 故障分级、现象、应急处理方案
一级故障:频繁 Minor GC,接口轻微卡顿
现象
- GC 日志短时间大量打印 Minor GC;
- 接口响应延迟小幅上涨,无大批量超时、无服务宕机;
- CPU 轻度升高,未打满。
根因
- 循环逻辑中持续 new 临时对象、DTO 未复用;
- 新生代 Eden 内存分配过小;
- 单次请求创建大量短生命周期大对象。
应急处理
- 临时调大新生代参数
-Xmn,扩大 Eden 容量; - 临时限流降低并发请求量。
长期优化
- 抽取通用 DTO,复用对象减少 new 次数;
- 局部方法内创建临时对象,避免提升生命周期;
- 拆分超大集合、分批处理数据。
二级故障:频繁 Full GC,CPU 打满,大量接口超时
现象
- 日志持续输出 Full GC;
- CPU 占用长期接近 100%;
- 前端大批量请求超时,服务吞吐量暴跌。
根因
- 静态 Map/List 无限存放数据,内存泄漏;
- 超大对象直接分配到老年代;
- 堆内存
-Xmx设置过小; - 老年代无连续内存存放晋升对象。
应急处理
- 立即开启 dump 快照,使用 MAT 工具分析内存占用;
- 临时调高
-Xmx堆最大内存缓解压力; - 临时下线高耗内存活动接口。
长期优化
- 清理全局静态集合,采用软 / 弱引用做业务缓存;
- 限制单次查询返回数据量,拆分大对象;
- 调整对象晋升年龄阈值,优化分代内存比例。
三级故障:StackOverflowError 栈溢出,服务崩溃
现象
控制台抛出 StackOverflowError,进程直接重启崩溃。
根因
- 递归逻辑无终止条件,无限递归;
- 多层方法循环嵌套过深;
- 单线程栈内存
-Xss配置偏小。
应急处理
- 紧急修复递归代码,增加递归深度判断终止条件;
- 临时调大
-Xss单栈内存大小。
长期优化
- 递归改循环实现业务;
- 递归业务增加最大深度拦截校验。
四级故障:Metaspace 元空间 OOM
现象
报错 java.lang.OutOfMemoryError: Metaspace,服务宕机。
根因
- CGLIB、动态代理、反射频繁生成新类;
- 热加载框架重复加载类,废弃类无法卸载;
- 元空间上限参数过小。
应急处理
- 临时调大
-XX:MaxMetaspaceSize; - 临时关闭非必要动态代理、热更新功能。
长期优化
- 缓存代理类,避免循环生成 Class;
- 定期清理无用动态类,配置类卸载参数。
五级故障:堆外直接内存 Direct Buffer OOM
现象
报错 Direct buffer memory,IO、文件上传接口异常。
根因
- NIO 使用 DirectByteBuffer 未手动释放堆外内存;
- 大文件一次性读取,缓冲区无限制;
- 堆外内存上限参数过小。
应急处理
- 限制单次上传 / 读取文件大小;
- 调高
-XX:MaxDirectMemorySize。
长期优化
- 使用 try-finally 主动释放堆外缓冲区;
- 文件流分段读写,不一次性加载全部文件。
| 故障等级 | 故障类型 | 核心现象 | 快速应急手段 |
|---|---|---|---|
| 一级 | 频繁 Minor GC | 接口轻微卡顿、GC 日志 Minor GC 多 | 调大 - Xmn、临时限流 |
| 二级 | 频繁 Full GC | CPU100%、大量请求超时 | 导出 dump、调高 - Xmx、下线高耗内存接口 |
| 三级 | 栈溢出 StackOverflowError | 程序直接崩溃重启 | 修复递归逻辑、增大 - Xss |
| 四级 | 元空间 OOM | Metaspace 溢出宕机 | 调大 MaxMetaspaceSize、关闭多余动态代理 |
| 五级 | 堆外内存 OOM | 文件 / IO 接口报错 | 限制文件大小、调高堆外内存上限 |
JVM 生产长期内存与 GC 调优规范
堆内存基础参数规范(Xms、Xmx、Xmn)
-Xms:堆初始内存;-Xmx:堆最大堆内存 生产规范:两者设置相等 原因:运行时堆不会动态扩容 / 缩容,避免扩容触发额外 GC 停顿,性能更稳定。-Xmn:新生代总大小(Eden + 两个 Survivor) 经验分配:新生代占整个堆内存 1/3 ~ 1/4; 高并发接口、大量临时对象场景适度调大 Xmn,减少 Minor GC 频率。- Eden 与 Survivor 默认比例 8:1:1 Eden 占新生代 80%,S0、S1 各 10%;保证复制算法备用区充足。
元空间 Metaspace 调优规范
- JDK8 无永久代,元空间使用本地堆外内存,默认无上限;
- 生产必须配置
-XX:MaxMetaspaceSize限制最大值,防止无限占用操作系统内存; - 频繁动态代理、反射、热更新项目,适当调高元空间上限;
- 尽量复用 Class、代理类,循环内禁止重复生成 CGLIB 动态类。
虚拟机栈参数 -Xss
-Xss控制单条线程栈内存大小;- 默认一般 1M;递归业务、多层方法嵌套可适度调大;
- 线程数量极多的服务不能设置过大,会直接耗尽操作系统内存。
堆外直接内存规范
- 配置
-XX:MaxDirectMemorySize限制 NIO 堆外缓冲区上限; - DirectByteBuffer 使用完毕必须手动释放,不要依赖 GC 回收;
- 大文件上传、网络 IO 接口做分片处理,禁止一次性加载超大缓冲区。
对象生命周期编码规范(从根源减少 GC 与内存泄漏)
- 短期临时对象在方法内创建,方法执行结束自动销毁,不要存入全局静态集合;
- 全局缓存优先使用软引用 SoftReference、弱引用 WeakReference,内存不足自动释放;
- 禁止使用无限扩容静态 List/Map 存放业务数据(用户、订单、优惠券);
- 循环中避免频繁 new 大对象,抽取对象复用、使用对象池;
- 批量查询分页、分片读取,杜绝一次性加载百万级数据进内存。
GC 日志与故障快照配置(线上必开)
- 开启完整 GC 日志,记录每次 GC 耗时、内存变化、停顿时间;
- 配置 OOM 自动导出堆 dump 文件:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/xxx/dump.hprof - dump 文件用于离线 MAT 工具分析内存泄漏、大对象占用,无 dump 则 OOM 故障无法定位。
引用类型使用规范
- 普通业务实体:强引用,短期局部使用无问题;
- 缓存场景:优先软引用,内存紧张自动清理;
- 容器 key、临时映射:弱引用,避免内存泄漏;
- 堆外内存监控场景:虚引用,跟踪缓冲区回收。
递归与大对象规避规范
- 递归增加最大深度判断,防止 StackOverflowError;复杂递归改用循环实现;
- 禁止一次性创建超大数组、超大集合,拆分分批处理;
- 避免超大对象直接分配到老年代,频繁触发 Full GC。
| 调优维度 | 配置 / 编码规范 | 核心目的 |
|---|---|---|
| 堆内存 Xms/Xmx | 数值保持一致 | 避免堆动态扩容产生额外 GC 停顿 |
| 新生代 - Xmn | 占堆内存 1/3~1/4,高并发调大 | 减少 Eden 快速填满,降低 Minor GC 频率 |
| 元空间 MaxMetaspaceSize | 设置固定上限 | 防止动态类耗尽本地内存,元空间 OOM |
| 栈内存 - Xss | 默认 1M,递归场景适度增大 | 避免栈溢出,多线程服务不宜过大 |
| 堆外内存 MaxDirectMemorySize | 设置合理上限 | 限制 NIO 缓冲区占用,防止 Direct buffer OOM |
| 代码对象管理 | 方法内创建临时对象,静态集合用软 / 弱引用 | 从根源杜绝内存泄漏,减少 Full GC |
| 故障日志配置 | 开启 GC 日志、OOM 自动 dump | 故障发生后可回溯定位内存问题 |