提升后端知识 第一天测试

2831 字
14 分钟
提升后端知识 第一天测试

📝 JVM 运行时数据区 · 全面通关测试题(试卷 + 答案)#

本测试题基于你第一天的学习内容设计,覆盖核心概念、细节辨析、场景应用三个层次。 目标:检验你能否把“读过的内容”变成“自己的武器”。


📄 试卷部分(请先独立完成,再对照答案)#


第一部分:基础填空题(每题 2 分,共 20 分)#

考察:核心定义是否准确记忆

  1. JVM 运行时数据区中,线程共享的区域是 ____________
  2. 线程私有的区域包括 __________________
  3. 程序计数器(Program Counter Register)是唯一一个在 Java 虚拟机规范中 ______(会/不会)出现 OutOfMemoryError 的区域。
  4. 每个方法被调用时,JVM 都会同步创建一个 ______,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
  5. 局部变量表中,64 位的数据类型(如 long、double)占用 ______ 个变量槽(Variable Slot),其他类型占用 1 个。
  6. Java 堆是垃圾收集器管理的主要区域,因此也被称作 ______
  7. JDK 8 及以后,方法区的实现从“永久代”变为了 ______(Metaspace)。
  8. 运行时常量池是 ______ 的一部分,在类加载后存放 Class 文件中的常量池表信息。
  9. 通过 String.intern() 方法可以在运行时将新的常量放入 ______ 中,这体现了运行时常量池的 ______ 特性。
  10. NIO 中使用的 ______ 内存并不是虚拟机运行时数据区的一部分,但由于被频繁使用也可能导致内存溢出。

第二部分:概念辨析题(每题 5 分,共 20 分)#

考察:能否区分容易混淆的概念

11. 虚拟机栈 vs 本地方法栈(5 分)

请用你自己的话,说清楚以下两个栈的本质区别

对比维度虚拟机栈 (VM Stack)本地方法栈 (Native Method Stack)
服务对象
执行内容
在 HotSpot 中的关系

12. 方法区 vs 堆(5 分)

一个类 User 被加载后,以下内容分别存放在哪个区域?

  • new User() 创建的对象实例 → ______
  • User 类的字段信息、方法字节码 → ______
  • User 类的静态变量 static int count______
  • 字符串常量 "hello"______(JDK 8 及以后)

13. 栈帧(Stack Frame)的组成(5 分)

请列出栈帧中包含的 4 个核心组成部分,并简要说明每个部分的作用。

组成部分作用说明

14. 字面量 vs 符号引用(5 分)

请将以下内容归类到“字面量”或“符号引用”:

内容分类(字面量 / 符号引用)
"Hello World"
final int MAX = 100 中的 100
java/lang/String 类的全限定名
方法名 sayHello() 及其描述符 ()V
3.14f

第三部分:场景应用题(每题 10 分,共 40 分)#

考察:能否把知识应用到真实线上问题中

15. StackOverflowError 场景分析(10 分)

某天你的线上服务突然抛出 java.lang.StackOverflowError,日志显示堆栈深度达到 10000+ 层。

  • 问题 1:这个异常最可能发生在 JVM 的哪个区域?(2 分)
  • 问题 2:请写出 2 种最常见的代码场景会导致这个异常。(4 分)
  • 问题 3:如果你在代码中使用了递归,应该如何避免这个异常?(4 分)

16. OutOfMemoryError: Java heap space 排查(10 分)

线上服务频繁出现 OutOfMemoryError: Java heap space,导致服务重启。

  • 问题 1:这个异常发生在 JVM 的哪个区域?(1 分)
  • 问题 2:请写出一个最简的 Java 代码示例,能重现这个 OOM。(3 分)
  • 问题 3:假设你已经拿到了 Heap Dump 文件,你会使用什么工具、按什么步骤来排查是哪个对象占用了最多内存?(6 分)

17. 方法区 OOM 场景(10 分)

在 JDK 8 环境中,一个框架不停地在运行时动态生成新的类(例如某些 ORM 框架或动态代理框架),导致出现了 OutOfMemoryError: Metaspace

  • 问题 1:JDK 8 中这个异常对应的区域是哪里?(1 分)
  • 问题 2:在 JDK 7 及以前,这个异常对应的区域叫什么?(1 分)
  • 问题 3:如果要临时解决这个问题,你会加什么 JVM 参数来限制这个区域的大小?(2 分)
  • 问题 4:从架构设计上,如何从根本上避免这个问题?(6 分)

18. 多线程与内存分布(10 分)

一个 Web 应用同时有 100 个用户在线,每个用户请求都会触发一次 UserService.getUserById() 调用。

  • 问题 1:这 100 个请求在 JVM 内存中,会创建多少个栈帧?(假设每个请求方法调用深度一致)(3 分)
  • 问题 2:这 100 个请求中,如果使用了 ThreadLocal 存储用户上下文信息,ThreadLocal 的数据是存放在哪个内存区域?它和栈是什么关系?(4 分)
  • 问题 3:程序计数器(PC)在每次线程切换时扮演什么角色?(3 分)

第四部分:综合论述题(20 分)#

考察:能否把多个知识点串联成体系

19. 完整描述一个对象的“一生”(20 分)

请结合你学到的运行时数据区知识,完整描述一个对象从编写代码运行时分配内存,再到被 GC 回收的全过程。

要求涵盖以下知识点:

  1. 对象在 方法区 中的“蓝图”(类信息)是如何来的?(4 分)
  2. 对象实例在 中是如何分配内存的?(4 分)
  3. 方法调用时,栈帧 是如何创建和销毁的?(4 分)
  4. 程序计数器 在这个过程中发挥了什么作用?(4 分)
  5. GC 如何判定这个对象“已死”?(4 分)

💡 提示:可以用一个具体的例子,比如 User user = new User(); user.sayHello();,串联起所有区域。

🎯 评分标准与自我评估#

分数区间等级说明
90 - 100 分🏆 精通级你不仅记住了概念,还能分析场景,第一天的学习效果远超预期!
70 - 89 分掌握级核心知识已过关,部分细节(如符号引用 vs 字面量)需要再巩固。
50 - 69 分📖 熟悉级大框架没问题,但需要回头复习一下易混淆的细节(如栈帧组成)。
< 50 分🔄 需复习建议用“费曼学习法”——假装教给别人,重新过一遍知识点。


📄 参考答案部分(做完后再看!)#


第一部分:填空题答案#

  1. Java堆方法区
  2. 程序计数器虚拟机栈本地方法栈
  3. 不会
  4. 栈帧(Stack Frame)
  5. 2
  6. GC堆
  7. 元空间
  8. 方法区
  9. 运行时常量池动态性
  10. 直接内存(Direct Memory)

第二部分:概念辨析题答案#

11. 虚拟机栈 vs 本地方法栈

对比维度虚拟机栈 (VM Stack)本地方法栈 (Native Method Stack)
服务对象① Java 方法② Native(本地)方法
执行内容③ Java 字节码④ 本地语言(如 C/C++)代码
在 HotSpot 中的关系两者合二为一

12. 方法区 vs 堆

  • new User()
  • User 类的字段信息、方法字节码 → 方法区(元空间)
  • static int count方法区(元空间)
  • "hello" 字符串常量 → 堆(JDK 8 字符串常量池在堆中)

13. 栈帧的 4 个核心组成部分

组成部分作用说明
① 局部变量表存储方法内的局部变量(基本类型、对象引用、返回地址)
② 操作数栈用于存储计算过程中的中间结果,类似 CPU 的寄存器
③ 动态链接将符号引用转换为直接引用,支持多态(如 invokevirtual
④ 方法返回地址记录方法执行完后应该返回到调用者的哪个位置继续执行

14. 字面量 vs 符号引用

内容分类(字面量 / 符号引用)
"Hello World"① 字面量
final int MAX = 100 中的 100② 字面量
java/lang/String 类的全限定名③ 符号引用
方法名 sayHello() 及其描述符 ()V④ 符号引用
3.14f⑤ 字面量

第三部分:场景应用题答案#

15. StackOverflowError 场景分析

  • 问题 1虚拟机栈(或本地方法栈)区域。(2 分)
  • 问题 2:① 无终止条件的递归调用(如 factorial() 无限递归);② 方法之间循环调用(A 调用 B,B 调用 A)。(4 分)
  • 问题 3:① 设置递归终止条件;② 递归层数较多时改用循环(迭代)实现;③ 增大栈空间 -Xss(治标不治本)。(4 分)

16. OutOfMemoryError: Java heap space 排查

  • 问题 1Java 堆。(1 分)

  • 问题 2:(3 分)

    java

    List<byte[]> list = new ArrayList<>();
    while (true) {
    list.add(new byte[1024 * 1024]); // 每次分配 1MB
    }
  • 问题 3:① 使用 Eclipse MATVisualVM 打开 Dump 文件;② 查看 Leak Suspects 报告,找到占用内存最大的对象;③ 查看该对象的 GC Roots 引用链,定位到是哪段业务代码持有引用;④ 修复代码(如释放引用、调整缓存大小)。(6 分)


17. 方法区 OOM 场景

  • 问题 1元空间(Metaspace)。(1 分)
  • 问题 2永久代(PermGen)。(1 分)
  • 问题 3-XX:MaxMetaspaceSize=256m(限制元空间最大值)。(2 分)
  • 问题 4:① 使用类加载器缓存,避免重复加载相同类;② 框架层面限制动态代理类的生成数量;③ 及时卸载不再使用的类(需要确保类加载器可回收)。(6 分)

18. 多线程与内存分布

  • 问题 1:100 个请求 × 每个请求的方法调用深度 = 100 × N 个栈帧(每个线程都有自己的虚拟机栈,栈帧数量 = 调用深度)。(3 分)
  • 问题 2ThreadLocal 的数据存储在 中(实际上是 ThreadLocalMap 作为 Thread 对象的成员变量,而 Thread 对象在堆中)。栈中只存储 ThreadLocal引用。(4 分)
  • 问题 3:程序计数器(PC)记录当前线程下一步要执行的字节码指令地址。线程切换时,JVM 保存当前线程的 PC,恢复下一个线程的 PC,确保切换回来后能继续执行。(3 分)

第四部分:综合论述题参考框架(20 分)#

19. 对象的“一生”参考回答

  1. 类加载(方法区)(4 分):JVM 通过 ClassLoader 加载 User.class 文件,解析出类的字段、方法、常量等信息,存入方法区(元空间)。这一步产生了对象的“蓝图”。
  2. 对象分配(堆)(4 分):执行 new User() 时,JVM 在 中分配内存。分配方式包括指针碰撞(内存规整)或空闲列表(内存不规整),并初始化对象头(Mark Word)和实例数据。
  3. 栈帧创建(虚拟机栈)(4 分):调用 user.sayHello() 时,在虚拟机栈中压入一个新的栈帧。栈帧中包含局部变量表(存储 user 引用)、操作数栈、动态链接和方法返回地址。方法执行完毕后,栈帧出栈销毁。
  4. 程序计数器参与(4 分):方法执行过程中,程序计数器始终指向下一条要执行的字节码指令的地址,保证方法按顺序执行。多线程切换时,PC 确保线程恢复到正确位置继续执行。
  5. GC 回收(堆)(4 分):当对象不再被任何 GC Roots(如栈中的局部变量、静态变量等)引用时,通过可达性分析判定对象“已死”。GC 会将其标记并清理,释放堆内存。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

提升后端知识 第一天测试
https://azhen.site/posts/文章/提升自我/day01-自测/
作者
发布于
2026-06-23
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
放弃思考等于引颈受戮
哈喽
欢迎来到我的博客!
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
15
分类
2
标签
5
总字数
51,671
运行时长
0
最后活动
0 天前
站点信息
构建平台
Vercel
博客版本
Firefly v6.12.3
文章许可
CC BY-NC-SA 4.0

文章目录