第61篇JVM内存区域2026版系列导航《Java 100 天进阶之路》完整目录 |⬅️ 上一篇第60篇并发编程面试压轴题 |➡️ 下一篇第62篇垃圾回收器详解待发布️ 本文阅读地图3 分钟速览第51~60篇拿下了并发编程本篇开启JVM调优与故障排查专题。JVM内存区域是理解GC、OOM、性能调优的基石搞懂这五大区域你就掌握了JVM的“地图”模块核心问题一句话回答五大区域JVM内存分哪几块程序计数器、虚拟机栈、本地方法栈、堆、元空间JDK 8线程私有哪些区域是线程独享的程序计数器、虚拟机栈、本地方法栈每个线程各有一份线程共享哪些区域是所有线程共用的堆、元空间所有线程共用需考虑并发安全堆对象存在哪里堆——所有new出来的对象和数组都在这里栈方法调用存在哪里虚拟机栈——每个方法调用对应一个栈帧元空间类的信息存在哪里元空间——存储类元数据、常量池、静态变量OOM场景哪些区域会内存溢出堆OOM、栈StackOverflowError/OOM、元空间OOM面试最爱问高频考点有哪些见文末 小节一、核心知识点JVM运行时数据区JDK 8JVM在执行Java程序时会将其管理的内存划分为5个核心运行时数据区根据线程私有/共享特性可分为两大类分类包含区域生命周期垃圾回收线程私有程序计数器、虚拟机栈、本地方法栈与线程同生共死基本不回收线程共享堆、元空间与JVM进程同生共死主要回收区域JDK 8 核心变更永久代PermGen被彻底移除方法区的实现改为元空间Metaspace直接使用本地内存Native Memory而非JVM堆内存。五大区域速览二、通俗讲解1分钟开心学1. 把JVM内存想象成一个图书馆程序计数器你正在读的书签——记录你读到第几页第几行当前执行到哪条字节码。线程切换时书签帮你找回刚才读到哪儿了。这本书签极小而且永远不会弄丢不会OOM。虚拟机栈你的“工作台”——每调用一个方法读一本书就在工作台上放一个文件夹栈帧方法执行完就把文件夹拿走。工作台太小时文件夹叠太多会塌StackOverflowError。本地方法栈专门处理“外文书籍”Native方法如C/C写的代码的工作台。堆图书馆的大仓库——所有new出来的对象和数组都存放在这里。仓库太大或太小都会出问题OOM所以需要管理员GC定期清理没人要的东西。元空间图书馆的目录卡柜——存储类的元数据类名、方法、字段等。JDK 8之前这个柜子放在仓库里永久代容易占满JDK 8后搬到隔壁的独立房间本地内存不再占用仓库空间。2. 一句话记住五大区域程序计数器记位置虚拟机栈管方法本地方法栈管Native堆存对象元空间存类信息。三、实操代码案例 场景说明3.1 栈溢出StackOverflowError演示无限递归是触发栈溢出的最典型场景publicclassStackOverflowDemo{privateintdepth0;publicvoidrecursion(){depth;recursion();// 无限递归}publicstaticvoidmain(String[]args){StackOverflowDemodemonewStackOverflowDemo();try{demo.recursion();}catch(StackOverflowErrore){System.out.println(栈溢出递归深度demo.depth);// 输出栈溢出递归深度约 10000~20000取决于栈大小}}}原因每个方法调用都会创建一个栈帧压入虚拟机栈无限递归导致栈帧不断堆积超过栈的最大深度时抛出StackOverflowError。可通过-Xss参数调整栈大小如-Xss1m。3.2 堆溢出OutOfMemoryError演示不断创建对象并保持引用是触发堆溢出的典型场景importjava.util.ArrayList;importjava.util.List;publicclassHeapOOMDemo{publicstaticvoidmain(String[]args){Listbyte[]listnewArrayList();try{while(true){// 每次分配 1MB无限循环list.add(newbyte[1024*1024]);}}catch(OutOfMemoryErrore){System.out.println(堆溢出已创建对象数list.size());// 输出堆溢出已创建对象数约 XXXX取决于 -Xmx 设置}}}原因堆内存被不断创建的对象占满且对象一直被list引用GC无法回收最终抛出OutOfMemoryError: Java heap space。可通过-Xmx参数调整堆最大大小。3.3 查看JVM内存参数# 查看JVM默认参数java-XX:PrintFlagsFinal-version|grep-EHeapSize|Metaspace|StackSize# 设置JVM参数运行程序java-Xms256m-Xmx1024m-Xss1m-XX:MetaspaceSize128m-XX:MaxMetaspaceSize256m HeapOOMDemo参数含义示例-Xms初始堆大小-Xms256m-Xmx最大堆大小-Xmx1024m-Xss每个线程的栈大小-Xss1m-XX:MetaspaceSize元空间初始大小-XX:MetaspaceSize128m-XX:MaxMetaspaceSize元空间最大大小-XX:MaxMetaspaceSize256m四、避坑要点错误/误区后果正确做法认为程序计数器会OOM概念错误程序计数器是唯一不会OOM的区域认为元空间在堆内调参错误JDK 8元空间使用本地内存不受堆大小限制无限递归不设终止条件StackOverflowError控制递归深度或改为迭代大量创建对象不释放引用OutOfMemoryError及时置null或使用局部变量混淆堆和栈的存储内容理解偏差堆存对象栈存局部变量和方法调用五、面试高频考点Q1JVM内存模型包含哪几个区域哪些是线程私有的五大区域程序计数器、虚拟机栈、本地方法栈、堆、元空间。线程私有程序计数器、虚拟机栈、本地方法栈每个线程独有。线程共享堆、元空间所有线程共用。Q2堆和栈的区别①用途栈存方法执行信息栈帧、局部变量堆存对象实例和数组。②生命周期栈随方法调用创建/销毁堆随对象创建/GC回收。③线程归属栈线程私有堆线程共享。④异常栈溢出StackOverflowError堆溢出OutOfMemoryError。Q3元空间和永久代的区别①内存位置永久代在JVM堆内存中元空间在本地内存中。②大小限制永久代受-XX:MaxPermSize限制元空间默认无上限受物理内存限制。③OOM风险永久代更容易OOM元空间更灵活。Q4程序计数器为什么不会OOM程序计数器只记录当前线程执行的字节码指令地址内存空间极小JVM规范未对该区域规定任何内存限制也不会抛出OutOfMemoryError。Q5栈帧中包含哪些内容栈帧包含四个部分局部变量表存储方法参数和局部变量、操作数栈执行运算时的临时数据、动态链接将符号引用转为直接引用、方法返回地址方法执行完后的返回位置。Q6什么情况下会抛出OutOfMemoryError: unable to create native thread创建了过多的线程JVM无法为新线程分配栈内存时抛出。注意这是本地内存不足导致的而非虚拟机栈本身的内存耗尽。 面试官追问陷阱加分题追问1“String s new String(abc)创建了几个对象分别存在哪里” 两个对象。abc字面量在字符串常量池元空间中创建一个对象new String()在堆中创建一个对象引用指向池中的字面量。s引用变量存在虚拟机栈的局部变量表中。追问2“static变量存在哪个区域” JDK 8之后static变量基本类型值直接存储对象引用存储指针存储在元空间中。static修饰的对象引用指向的对象本身仍在堆中。六、练习题分析题写出以下代码中变量a、b、obj、str在JVM内存中的位置栈/堆/元空间。classTest{staticinta10;intb20;voidmethod(){intc30;ObjectobjnewObject();Stringstrhello;}}思路a静态变量在元空间b实例变量在堆随对象c局部变量在栈obj引用在栈、对象在堆str引用在栈、字面量hello在字符串常量池元空间。代码题编写一个程序分别触发StackOverflowError和OutOfMemoryError并观察错误信息。场景题某线上服务频繁报OutOfMemoryError: Metaspace分析可能原因和解决方案。思路元空间存储类元数据如果应用动态加载了大量类如热部署、动态代理、Groovy脚本等元空间可能被占满。解决方案增大-XX:MaxMetaspaceSize或排查是否存在类加载器泄漏。 你的学习进度当前第61篇 / 共108篇 ·进阶篇JVM调优与故障排查第61~70篇✅ 已完成基础篇44篇 第45~61篇 正在学第61篇⏳ 待学习第62~108篇 完整目录 学习指南 | 订阅本专栏不错过每一篇 下一篇文章预告下一篇《第62篇垃圾回收器详解》内容简介Serial、Parallel、CMS、G1、ZGC 等垃圾回收器原理与选型GC日志分析JVM调参实战。JVM调优专题持续深入拿下垃圾回收器《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇建议收藏 关注一起100天拿offer 点击关注我更新后第一时间收到推送