先说结论

主要包括程序计数器、虚拟机栈、本地方法栈、堆和方法区。

线程私有区域

程序计数器、虚拟机栈和本地方法栈随线程创建和销毁。虚拟机栈以栈帧为单位保存局部变量表、操作数栈和返回地址等信息。

线程共享区域

堆与方法区由多个线程共享。堆是对象分配和垃圾回收的主要区域,方法区保存类元数据、运行时常量池等信息。

常见异常

递归过深可能产生 StackOverflowError;对象无法分配可能产生 Java heap space;类元数据过多可能导致 Metaspace OOM。

一次方法调用如何执行

调用方法时创建栈帧,参数和局部变量进入局部变量表,字节码借助操作数栈完成计算。方法正常返回或抛出未捕获异常时栈帧弹出。局部变量可能保存堆对象的引用,但引用变量和对象实体不是同一回事。

常见问题

追问 1:堆和栈最本质的区别是什么?

栈服务线程的方法调用,生命周期与栈帧一致;堆服务对象存储,由线程共享并受 GC 管理。“栈快堆慢”不是本质定义。

追问 2:元空间会 OOM 吗?

会。大量动态生成类、类加载器泄漏或上限过小都可能导致 Metaspace OOM,应分析类数量与 ClassLoader 生命周期。

追问 3:对象一定在堆上吗?

语义上对象通常由堆管理,但 JIT 可对未逃逸对象做标量替换,甚至消除分配,不能机械回答“一定”。