说一下 JVM 的内存结构(运行时数据区)有哪些?每一块的作用是什么?
1 个回答
过去不重要,未来才重要。风无尘# 总览 | 区域 | 线程共享/私有 | 主要内容/作用 | 典型错误 | | ----------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | | 程序计数器(PC Register) | 私有 | 指向当前线程正在执行的字节码指令地址(本地方法时值未定义)。用于线程切换后恢复执行点。 | — | | Java 虚拟机栈(JVM Stack) | 私有 | 由一帧帧(Stack Frame)组成:**局部变量表**、**操作数栈**、**动态链接**、**返回地址**;随方法调用/返回入栈出栈。 | `StackOverflowError`(栈太深),`OutOfMemoryError: unable to create new native thread`(系统线程受限) | | 本地方法栈(Native Method Stack) | 私有 | 为 JNI/本地代码服务的调用栈。 | 同上,溢出/创建失败 | | 堆(Heap) | 共享 | **对象、数组**的主要存放区;GC 管理。HotSpot 里通常分 **新生代(Eden + S0/S1)** 与 **老年代**;支持 **TLAB**、大对象直接入老年代等。 | `OutOfMemoryError: Java heap space`、`GC overhead limit exceeded` | | 方法区(Method Area) | 共享 | 存 **类元数据、常量、静态变量、JIT 信息** 等。HotSpot 实现随版本不同:<br>• **JDK7 及以前**:方法区落在 **PermGen**(永久代)<br>• **JDK8+**:移除 PermGen,改为 **Metaspace(元空间,使用本地内存)** | JDK7:`OutOfMemoryError: PermGen space`<br>JDK8+:`OutOfMemoryError: Metaspace` | | 运行时常量池(Runtime Constant Pool) | 共享 | 属于方法区的一部分,存 class 常量(字面量、符号引用)与运行期生成的常量;**字符串常量池(intern)对象本身在堆**(JDK7+)。 | 常与方法区 OOM 一起出现 | | 代码缓存(Code Cache) | 共享 | JIT(C1/C2)编译生成的本地机器码缓存(含各类 CodeHeap)。 | `OutOfMemoryError: CodeCache is full` | | 直接内存(Direct Memory,非规范区) | 共享 | NIO `DirectByteBuffer` 使用的**堆外内存**;不在堆里,由 GC 间接回收,**上限可由 `-XX:MaxDirectMemorySize` 控制**。 | `OutOfMemoryError: Direct buffer memory` | # 关键细节与调优点 * **堆** * 新生代用于短命对象,Minor GC;老年代存活久对象,Major/Full GC。 * **TLAB**:每线程在 Eden 划一小块,减少锁竞争,`-XX:+UseTLAB`(默认启用)。 * 常用参数:`-Xms/-Xmx`(起始/最大堆),`-XX:NewRatio`、`-XX:SurvivorRatio`、选择 GC(G1/ZGC/Shenandoah)。 * **方法区 / 元空间** * **JDK8+** 使用 **Metaspace**(向系统本地内存申请),上限:`-XX:MaxMetaspaceSize`。 * 存放:类的元数据(字段/方法/常量池结构、注解等),卸载类可回收元空间。 * **运行时常量池 & 字符串** * 常量池结构在方法区;`String.intern()` 返回的字符串对象 **JDK7+ 在堆**。 * **代码缓存** * JIT 编译后的机器码放这里;上限:`-XX:ReservedCodeCacheSize`。满了会降级解释执行或抛 OOM。 * **直接内存** * 适合高吞吐 I/O 与零拷贝;受 `-XX:MaxDirectMemorySize` 限制,释放依赖引用变为不可达 + Cleaner/GC 触发。 # 常见问题定位 * 频繁 Full GC/吞吐低:查看 GC 日志与堆直方图(`jcmd GC.heap_info`, `jmap -histo`),检查**大对象/长寿对象**与**索引/缓存策略**。 * Metaspace OOM:多 ClassLoader 动态生成/热部署泄漏;加上限、做类卸载、减少生成。 * CodeCache 满:增大 `ReservedCodeCacheSize` 或减少 JIT 复杂度(关闭某些编译)。 * 直接内存 OOM:检查 NIO/Netty Buffer 使用与释放,调 `MaxDirectMemorySize`。 # 版本差异(提纲挈领) * **JDK7-**:方法区=PermGen;字符串常量池在堆外(JDK7 迁入堆)。 * **JDK8+**:移除 PermGen → **Metaspace(本地内存)**;字符串常量池在堆;默认 G1(JDK9+ 默认)。 * **JDK11/17**:更现代 GC 可选(ZGC/Shenandoah),低停顿、堆外碎片管理更优。 # 常用参数速查 * 堆:`-Xms` / `-Xmx` * 线程栈:`-Xss` * 元空间:`-XX:MaxMetaspaceSize` * 代码缓存:`-XX:ReservedCodeCacheSize` * 直接内存:`-XX:MaxDirectMemorySize` * GC 日志(JDK9+):`-Xlog:gc*:file=gc.log:time,uptime,level,tags`发布于 2025-08-18 20:06 •IP属地 吉林举报评论收藏
公众号进入网站体验更佳

