JVM运行时数据区分为线程私有(程序计数器、虚拟机栈、本地方法栈)和线程共享(堆、方法区/元空间)两类,支撑字节码执行、对象分配、方法调用与垃圾回收。

可以把它想象成一个 Java 程序运行时的“办公室”——不同岗位的人(线程)各司其职,各自有专属工位,也有大家共用的资料室和仓库。JVM 运行时数据区就是这个办公室的布局规划,它把内存划分为几个功能明确的区域,让程序跑得清楚、安全、高效。
先分两类:谁用的?什么时候用?
所有区域按“归属”和“寿命”能快速归为两类:
- 线程私有区域:每个线程独享一份,随线程出生而创建、死亡而销毁。包括——程序计数器、Java 虚拟机栈、本地方法栈。
- 线程共享区域:所有线程一起读写,生命周期和 JVM 进程一致(启动就有,退出才清)。包括——堆、方法区(Java 8+ 叫元空间)。
五个核心区域,一句话定位
程序计数器:每个线程的“书签”。记录当前执行到哪一行字节码,线程切换回来时靠它接着读。极小、线程私有、不会 OOM。
Java 虚拟机栈:存放方法调用的“临时记事本”。每次调用方法就压一个栈帧(含局部变量、操作数栈等),方法结束就弹出。栈深度超限会报 StackOverflowError。
本地方法栈:和虚拟机栈类似,但专供 native 方法(比如用 C 写的底层逻辑)使用。HotSpot 中两者常合二为一。
堆:最大、最核心的共享内存区,几乎所有的对象实例和数组都在这里分配。是垃圾回收的主要战场,分新生代(Eden + Survivor)、老年代。
方法区(元空间):存“类的说明书”——类结构、常量、静态变量、JIT 编译后的代码。Java 8 起,永久代被移除,改用本地内存的元空间,OOM 风险转向本地内存耗尽。
两个容易混淆但必须厘清的概念
不是 Java 内存模型(JMM):运行时数据区讲的是“内存物理划分”,是 JVM 实际怎么摆数据;JMM 讲的是“多线程读写共享变量的抽象规则”,解决可见性、有序性问题,两者完全不在一个层面。
直接内存不属规范,但很常用:NIO 中用 ByteBuffer.allocateDirect() 分配的内存,绕过堆,直接在操作系统内存中开空间。它不属于运行时数据区定义范围,但频繁使用,且可能引发 OOM(比如没限制 DirectMemorySize)。


















