news 2026/6/27 6:59:02

Java面试-02-JVM虚拟机

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java面试-02-JVM虚拟机

JVM虚拟机面试题(完整版)

目录

  • 1. JVM主要组成部分及作用
  • 2. 类加载器
    • 2.1 类加载器分类
    • 2.2 类加载机制及过程
    • 2.3 双亲委派机制
  • 3. 运行时数据区
  • 4. 本地方法接口
  • 5. JVM垃圾回收
    • 5.1 垃圾回收机制
    • 5.2 对象回收判断算法
    • 5.3 垃圾回收算法
    • 5.4 Java堆分代模型
    • 5.5 垃圾回收器
    • 5.6 对象分配与回收策略
    • 5.7 对象流转完整过程
  • 6. JVM常见异常及排查
  • 7. JVM调优
    • 7.1 JVM调优步骤
    • 7.2 调优核心原则
    • 7.3 可视化监控工具
    • 7.4 实际项目调优案例
  • 8. 高频面试问题

1. JVM主要组成部分及作用

JVM核心分为两大子系统两大组件

两大子系统

  1. 类加载器子系统:负责将.class字节码文件加载到JVM内存中
  2. 执行引擎子系统:执行加载后类中的字节码指令,会先编译为机器码再执行

两大组件

  1. 运行时数据区:JVM内存区域,存储程序运行数据
  2. 本地方法接口:与native本地方法交互的接口

2. 类加载器

2.1 类加载器分类

  1. 启动类加载器(Bootstrap):加载Java核心类库(rt.jar
  2. 扩展类加载器(Extension):加载JDK扩展目录下的jar包
  3. 应用类加载器(App):加载项目classpath下的类文件
  4. 自定义类加载器:加载自定义路径的JAR/类文件

2.2 类加载机制及过程

类加载完整流程:加载 → 连接 → 初始化

  1. 加载:通过类加载器读取.class文件,加载到JVM内存
  2. 连接
    • 校验:验证字节码文件的安全性、正确性
    • 准备:为静态变量分配内存,设置默认初始值
    • 解析:将常量池符号引用转换为直接引用
  3. 初始化:执行静态代码块,为静态变量赋实际值

2.3 双亲委派机制

  • 定义:类加载器收到加载请求时,优先委托父类加载器执行,递归向上直到启动类加载器;父类无法加载时,子类才尝试加载
  • 核心优势:避免类重复加载,保证核心类安全

3. 运行时数据区

JVM内存模型分为5个区域,按线程共享/私有划分:

区域名称作用存储内容线程特性
堆(Heap)JVM最大内存区域,GC主要区域对象实例、数组共享
方法区存储类元数据类信息、常量、静态变量、编译后代码共享
虚拟机栈方法执行内存模型局部变量表、操作数栈、方法返回地址私有
程序计数器记录线程执行字节码行号当前执行指令地址私有
本地方法栈执行native方法服务本地方法调用信息私有

4. 本地方法接口

  • 作用:用于JVM与底层操作系统、本地native方法进行交互
  • 场景:调用C/C++实现的底层系统功能

5. JVM垃圾回收

5.1 垃圾回收机制

  1. 自动回收堆中无引用、不可达的垃圾对象,释放内存
  2. System.gc():手动触发GC(不保证立即执行)
  3. finalize():GC回收对象前自动调用的方法

5.2 对象回收判断算法

  1. 引用计数法
    • 给对象添加计数器,引用+1,失效-1;计数器=0可回收
    • 缺点:无法解决对象循环引用问题
  2. 可达性分析算法(JVM默认)
    • GC Roots为起点,遍历引用链,不可达对象可回收
    • 可作为GC Roots的对象
      1. 虚拟机栈中引用的对象
      2. 方法区静态变量引用的对象
      3. 方法区常量引用的对象
      4. 本地方法栈引用的对象

5.3 垃圾回收算法

算法原理优点缺点
标记-清除先标记存活对象,再清除垃圾简单产生内存碎片
复制算法内存分两块,存活对象复制到空块,清空原块无碎片浪费50%内存
标记-整理标记后将存活对象移到一端,清理边界外内存无碎片移动对象开销大
分代收集新生代用复制,老年代用标记清除/整理综合效率最高逻辑复杂

5.4 Java堆分代模型

新生代(对象存活率低)
  • 分区:Eden : From Survivor : To Survivor =8:1:1
    新生代分为三个区域,分别是一个 Eden 区和两个 Survivor 区,它们的默认比例是 8:1:1。Eden 区:新创建的对象首先会被分配到 Eden 区。当 Eden 区满时,会触发一次 Minor GC(新生代垃圾回收)。Survivor 区:在 Minor GC 时,Eden 区中存活的对象会被移动到其中一个 Survivor 区。同时,From Space 中之前存活的对象,如果经过这次垃圾回收仍然存活,并且年龄达到一定阈值(默认是 15,可以通过-XX:MaxTenuringThreshold参数调整),会被移动到老年代;如果未达到阈值,则会和 Eden 区移动过来的对象一起被复制到另一个 Survivor 区。之后,两个Survivor 的角色会互换
  • 垃圾回收:Minor GC,频率高、速度快
  • 算法:复制算法
老年代(对象存活率高)
  • 存储:长期存活对象、大对象
    年龄阈值:对象在 Survivor 区经过多次 Minor GC 后,年龄达到一定阈值,会被晋升到老年代。大对象直接进入:当创建的对象占用内存超过一定大小(可以通过-XX:PretenureSizeThreshold参数设置)时,会直接在老年代分配内存。Survivor 区空间不足:如果在 Survivor 区中,相同年龄的所有对象大小总和大于 Survivor区空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。
  • 垃圾回收:Full GC/Major GC,频率低、速度慢
  • 算法:标记-清除 / 标记-整理
元空间(Java8+,替代永久代)
  • 永久代(Java 7 及以前)存储内容:主要存储类的元数据信息(如类的结构、方法、字段等)、常量池、静态变量等。永久代的大小在启动时就需要指定,且不能动态扩展。问题:由于永久代的大小是固定的,如果加载的类过多,或者常量池过大,容易导致OutOfMemoryError:PermGenspace异常。元空间(Java 8 及以后)存储内容:同样用于存储类的元数据信息,但与永久代不同的是,元空间使用的是本地内存(Native Memory),而不是 JVM 堆内存。优点:元空间的大小可以动态扩展,只要系统的本地内存足够,就不会出现永久代那样的内存溢出问题。
  • 存储:类元数据、常量池

5.5 垃圾回收器

新生代收集器
  1. Serial:单线程、复制算法、停顿用户线程
  2. ParNew:Serial多线程版本
  3. Parallel Scavenge:关注高吞吐量
老年代收集器
  1. Serial Old:Serial老年代版本,标记-整理
  2. Parallel Old:多线程、标记-整理
  3. CMS:最短回收停顿,并发回收
整堆收集器
  • G1:跨代收集,兼顾吞吐量与停顿时间

5.6 对象分配与回收策略

  1. 新对象优先分配在Eden区
  2. 大对象直接进入老年代
  3. 长期存活对象晋升老年代(默认年龄阈值15)
  4. Eden区满 →Minor GC
  5. 老年代满 →Full GC

5.7 对象流转完整过程

  1. 创建 → 分配到Eden区
  2. Eden满 → Minor GC → 存活对象进入Survivor
  3. Survivor中对象年龄递增 → 达标晋升老年代
  4. 老年代满 → Full GC回收整个堆
  5. 无引用 → 被GC彻底回收

6. JVM常见异常及排查

StackOverflowError(栈溢出)

  • 原因:无限递归、方法调用层级过深、大量局部变量
  • 排查:检查递归逻辑、方法调用链

OutOfMemoryError(堆溢出/OOM)

  • 原因:加载数据过大、集合未释放、死循环创建对象、内存参数过小
  • 排查:分析dump文件、检查对象引用、优化代码

7. JVM调优

7.1 JVM调优步骤

  1. 监控:使用JConsole、VisualVM查看GC日志、堆内存快照
  2. 分析:看日志,判断GC频率、停顿时间是否异常
    Minor GC执行时间不到50ms;Minor GC执行不频繁,约10秒一次;Full GC执行时间不到1s;Full GC执行频率不算频繁,不低于10分钟1次;
  3. 调整:修改内存参数、GC收集器、分代比例
  4. 验证:持续监控,找到最优参数

7.2 调优核心原则

  1. -Xms(初始堆)与-Xmx(最大堆)设置为相同值,减少GC次数
  2. 新生代:老年代默认比例1:2,可根据场景调整
  3. 高并发场景优先使用并行收集器/G1
  4. 避免大对象直接进入老年代

7.3 可视化监控工具

  • JConsole:JDK自带,监控内存、线程、GC
  • VisualVM:功能全面的JVM分析工具
  • MAT:分析OOM dump文件,定位内存泄漏

7.4 实际项目调优案例

项目场景:知识图谱工具部署后响应慢、频繁OOM
问题原因:数据导入创建大量临时大对象,堆内存不足
调优过程

  1. 增大堆内存:-Xms4g -Xmx4g
  2. 调整分代比例:-XX:NewRatio=1(新生代:老年代=1:1)
  3. 启用GC收集器:-XX:+UseG1GC
  4. 开启dump:-XX:+HeapDumpOnOutOfMemoryError
  5. 代码优化:使用对象池、重构导入逻辑(CSV导入替代内存操作)
    最终方案:代码重构+合理JVM参数,解决OOM问题

8. 高频面试问题

  1. 对象一定分配在堆中吗?
    不一定。无逃逸对象可在栈上分配;简单对象可通过标量替换拆分存储。

  2. Minor GC和Full GC区别?

    • Minor GC:新生代回收,速度快、频率高
    • Full GC:整堆回收,速度慢、频率低
  3. 永久代和元空间区别?

    • 永久代:Java7及以前,使用堆内存,固定大小
    • 元空间:Java8+,使用本地内存,可动态扩展
  4. CMS收集器特点?
    并发收集、低停顿、适用于互联网服务端

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/27 6:57:35

低代码会取代前端吗?

每隔几个月,技术社区里就会有人把这个话题翻出来吵一轮。一方说低代码拖拖拽拽就能搭页面,前端岗位的护城河已经塌了。另一方说低代码做不了复杂交互,离了专业前端寸步难行。两边各执一词,围观的人越看越糊涂。这个焦虑的根源在于…

作者头像 李华
网站建设 2026/6/27 6:55:58

阿姆智创ARM-3576A开发板方案,赋能机器视觉与协作机械臂设备交互控制升级

在工业智能化转型浪潮中,机器视觉作为设备的“感知之眼”、协作机械臂作为柔性作业的“执行之手”,二者融合应用已成为自动化产线、精密检测、柔性分拣等场景的主流形态。高性能嵌入式开发板是串联视觉采集、智能分析、运动控制的重要枢纽,其…

作者头像 李华
网站建设 2026/6/27 6:51:50

一文吃透 4 层 Loop Engineering,LangChain 官方博文深度拆解

现在AI行业里慢慢形成了统一认知:大模型本身算不上核心壁垒,Loop Engineering循环工程才是真正拉开差距的关键。 LangChain官方博客前段时间更新了一篇名为《The Art of Loop Engineering》的文章,完整梳理清楚循环工程整套架构逻辑。 今天就…

作者头像 李华
网站建设 2026/6/27 6:45:50

Claude Code教程 -03- 文件目录解析及运行逻辑

Lison <dreamlison163.com>, v1.0.0, 2026.06.21 Claude Code教程 -03- 文件目录解析及运行逻辑 文章目录Claude Code教程 -03- 文件目录解析及运行逻辑Claude Code 本地目录结构解析核心目录详解projects目录&#xff1a;项目数据的大本营history.jsonl&#xff1a;全局…

作者头像 李华
网站建设 2026/6/27 6:43:55

2026电商客服外包行业盘点:5 家主流服务商对比,附价格与选型参考

据《2025 年中国电商客户服务外包行业发展白皮书》公开数据显示&#xff0c;2025 年国内电商客服外包市场规模保持稳步增长&#xff0c;超 65% 的中小电商商家、40% 以上的头部品牌已通过外包模式优化服务体系&#xff0c;降本提效成为行业普遍诉求。 面对市场上数百家服务商&a…

作者头像 李华