JVM五大内存区域分工明确:堆存对象实例、线程共享、GC主战场;栈存方法调用帧、线程私有;元空间存类元数据、本地内存分配;程序计数器和本地方法栈辅助执行,几乎不OOM。

直接看五大区域怎么分工、谁存什么、出问题往哪查,比死记概念有用得多。
堆(Heap)——对象的主仓库
所有 new 出来的对象、数组都默认存在这里,线程共享,是 GC 主战场。它被划分为新生代(Eden + S0/S1)和老年代,不同年龄的对象按规则晋升。如果频繁出现 OutOfMemoryError: Java heap space,说明对象太多或内存泄漏,得用 jmap + jhat 或 MAT 工具分析堆快照,重点查大对象、长生命周期集合、未关闭的资源引用。
虚拟机栈(Java Stack)——每个线程的执行现场
线程私有,方法调用时压入栈帧,存局部变量、操作数栈、返回地址等。栈深度超限会抛 StackOverflowError(比如递归太深);栈总空间不足则报 OutOfMemoryError(多线程创建过多)。可通过 -Xss 参数调栈大小,但不能盲目加大,否则挤占堆空间。
方法区(JDK8+ 是元空间 Metaspace)——类的元数据中枢
线程共享,存类结构、常量池、静态变量、JIT 编译代码。JDK8 后从堆里挪到本地内存,不再受 -XX:MaxPermSize 限制,改用 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 控制。若报 OutOfMemoryError: Metaspace,常见于动态生成大量类(如反复加载/卸载 Jar、使用 CGLIB/ASM 过度代理),需检查类加载器是否泄漏。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
程序计数器与本地方法栈——辅助执行的“小角色”
程序计数器记录当前线程执行到哪条字节码指令,极小且线程私有,几乎不会出错;本地方法栈服务 native 方法(如 File I/O、JNI 调用),异常类型和虚拟机栈类似。这两块区域一般不主动调优,除非遇到罕见的 native 层崩溃或 JNI 调用卡死,才需结合 hs_err 日志和系统级工具排查。
怎么验证和观察实际分布?
启动时加参数开启监控:
- -XX:+PrintGCDetails -Xloggc:gc.log:看堆回收行为
- -XX:+PrintClassHistogram:运行时按 Ctrl+Break 查实时对象统计
- jstat -gc <pid>:实时查看各区内存使用与 GC 次数
- jcmd <pid> VM.native_memory summary:看元空间、堆外内存占用
不复杂但容易忽略的是:线程私有区域(栈、PC、本地栈)随线程生灭,而堆和方法区贯穿整个 JVM 生命周期,它们才是 OOM 的主要来源,也是调优的核心靶区。

















