首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >搞定 JVM 面试:高频问题全解析与应对技巧

搞定 JVM 面试:高频问题全解析与应对技巧

作者头像
varin
发布2025-09-28 13:05:51
发布2025-09-28 13:05:51
1000
代码可运行
举报
文章被收录于专栏:/root/root
运行总次数:0
代码可运行

什么是JVM

  1. 回答思路:
    1. 定义
    2. 作用
    3. 功能
    4. 组成

  1. 定义: JVM是指Java虚拟机,本质上是运行在计算机上的程序,职责是运行Java字节码文件。
  2. 作用:做到**跨平台,编写一次,到处运行**。
  3. 功能:
    1. 解释和运行:将class文件解释称为机器码并运行
    2. 内存管理:自动为对象/方法分配内存,GC自动回收垃圾对象
    3. 即时编译:对热点代码进行优化,提升效率
  4. 组成:
    1. 第一部分:源代码通过编译生成class文件
    2. 第二部分:在jvm中,先通过类加载器将对象数据内存中,用到的内存称为运行时数据区,其中包括(程序计数器,本地方法栈和虚拟机栈,堆,方法区)
    3. 第三部分:执行引擎(包含 解释器/即时编译器/垃圾回收器)
    4. 第四部分:本地接口:由C++或C编写的方法

总结:

字节码文件的组成

  1. 回答思路:
    1. 查看字节码文件的工具
    2. 字节码文件的组成
    3. 看字节码文件应用场景

  1. 工具:
    1. Idea插件:jclasslib
    2. 服务器环境查看:javap -v
  2. 组成:
  3. 场景:为了帮助程序猿更好的理解jvm底层

聊一聊运行时数据区

  1. 回答思路
    1. 分别从:程序计数器/栈/堆/方法区回答

  1. 分类:
    1. 线程不共享:程序计数器/虚拟机栈/本地方法栈
    2. 线程共享:堆/方法区
  2. 程序计数器:每个线程通过程序计数器记录当前字节码执行的地址,从而实现指令的跳转,分支,异常等逻辑。
    1. 例如:有两个线程,线程A运行时,线程B时阻塞的,在某一时刻,B抢到了时间片,开始运行,此时,程序计数器就会记录线程A在当前执行到指令的位置,为了下次A的到时间片的时候,从上次中断的地方开发运行。
  3. Java虚拟机栈:
    1. 采用栈的数据结构管理方法中的数据,
    2. 一个方法有一个栈帧(包括:局部变量表,操作数栈,帧数据),通过栈帧存储知道方法的执行顺序
    3. 例如
  1. 本地方法栈:
    1. 使用native修饰的方法,使用C++或者C编写的方法
  2. 方法区:
  3. 堆:
    1. 空间最大的一块,创建出来的对象都存在堆中
  4. 方法区:
    1. 会为每一个类准备一块空间,用于加载类的基本信息
代码语言:javascript
代码运行次数:0
运行
复制
2. 存放运行时常量池
3. 存放字符串常量池
    1. 字符串常量

总结:

说一说在哪些区域会出现内存溢出,会有什么现象?

  1. 回答思路:
    1. 解释内存溢出
    2. 说明会出现溢出的区域
    3. 分别说明:每个区域内存溢出的现象

  1. 内存溢出概念:
    1. 是指内存中的某一块区域使用量超过了允许的最大值
  2. 在运行时数据区中,只有程序计数器不会出现内存溢出,因为每个线程的程序计数器长度时固定的。
  3. 堆内存溢出现象:
    1. 原因:分配对象空间超出了最大值
    2. 模拟方式:不停创建对象
    3. 抛出OutOfMemoryError异常,提示java heap space
  4. 栈内存溢出现象:
    1. 原因:栈帧空间超出了最大值
    2. 模拟方法:不停创建对象
    3. 抛出stackOverFlowError
  5. 方法区内存溢出现象:
    1. 原因:方法区存放类的基本信息过多
    2. 抛出异常:jdk8提示(Metaspace) ,jdk7提示:permGen space
  6. 直接内存溢出现象
    1. 原因字节内存空间超过了最大值
    2. 异常提示信息:Direct buffer memory

总结:

JVM在jdk6~8之间在内存区域有什么不同?

  1. 回答思路:
    1. 从两个方面:方法区的实现以及字符串常量池的位置

  1. 方法区的实现
    1. 以Hotspot举例:
      1. 在jdk7之前,方法区存在于堆区域的永久代空间
      2. 在jdk8之后,方法区存放在元空间,元空间位于直接内存中。
      3. 元空间替换永久代的原因:
        1. 提供内存上限:不使用JVM内存,直接使用操作系统内存
        2. 优化垃圾回收机制,堆和方法区分离,职责更加单一
  2. 字符串常量池
    1. 位置:
      1. jdk7之前,存储在方法区中,运行时常量池包含字符串常量池
      2. jdk7:字符串常量池从方法区拿到了堆中,运行时常量池还在方法区中
      3. jdk8:元空间代替永久代,字符常量池还在堆中
      4. 总结:jdk7后,字符串常量池存在于堆中,运行时常量池在方法区中

总结:

  1. jdk6
  1. jdk7
  1. jdk8

类的生命周期

  1. 回答思路:
    1. 从类的加载,连接(验证,准备,解析),到初始化,最后说卸载

  1. 加载:
    1. 通过类加载器根据类的**全限定类名,以二进制的形式获取字节码信**息
    2. 加载完成后,JVM会将字节码信息保存到内存的方法区中,生成一个**InstanceKlass**对象
    3. 也会在堆中生成一个java.lang.Class对象
  2. 连接:
    1. 验证:验证字节码信息的魔数/主版本号和副版本号等信息
    2. 准备:给静态变量赋**默认值**
    3. 解析:将常量池中的符号引用换成直接引用
  3. 初始化:会执行静态代码块代码,并会静态变量赋值
  4. 卸载:使用完成,释放对象
    1. 卸载需要满足的条件:类的所有实例和子类的所有实例被回收,加载该类的类加载器被回收,该类没有在任何地方被引用。
  5. 总结

什么是类加载器

  1. 回答思路:
    1. 类加载器的作用
    2. 启动类加载器
    3. 扩展类加载器
    4. 应用程序加载器
    5. 自定义类加载器
  2. 答案:

  1. 作用:负责在类加载过程中将字节码文件以二进制的方式加载到内存中
  2. 分类:
    1. 启动类加载器:Bootstrap
      1. 加载最核心的类:默认加载/jre/lib目录下的jar包
      2. 获取加载器器时,返回Null。
    2. 扩展类加载器:Extension
      1. 加载通用类:默认加载/jre/lib/ext
      2. 获取加载器时,返回:PlaformClassLoader
    3. 应用程序加载器:application
      1. 用户自定义的类
      2. 获取加载器时,返回ApplicationClassLoader
    4. 用户自定义的类
      1. 实现需要继承ClassLoader类,重写findClass方法
  3. 总结

什么是双亲委派机制

  1. 回答思路:
    1. 回答什么是父类加载器
    2. 回答什么是双亲
    3. 回答双亲作用

核心:向上查找,向下加载

  1. 加载器父辈关系(小到大):自定义类加载器》applicatioin》extension〉bootstrap
  2. 概念:当一个类加载器接收到加载的任务时**,会向上查询是否加载过,如果没有找到,会有顶向下进行加载**。
  3. 作用:
    1. 保证类加载的安全性
    2. 避免重复加载
  4. 总结

如何打破双亲委派机制

  1. 回答思路:
    1. 重写loadClass方法

  1. 总结:

如何判断堆上的对象没有被引用

  1. 回答思路:
    1. 说出垃圾回收机制两个判断对象是否可以被回收的方法
    2. 并说出两种方法的好坏处。
  2. 答案:

判断对象是否可以被回收,有两种方法

  1. 引用计数法: 1. 会为每个对象添加一个计数器,对象被引用加1,取消引用减1,为0时可以回收 2. 存在问题:两个对象可能存在循环引用的问题,造成死锁,出现内存泄露。
  2. 可达性分析法
    1. 可达性分析法将对象分为了GC Root对象和普通对象
    2. 判断:只要对象在引用链上对象就不会被回收。
    3. GC对象包括:线程对象,监视器对象,本地方法调用时使用的全局对象,系统类加载器加载的java.lang.Class对象
  3. 总结:

JVM中都有哪些引用类型

  1. 回答思路
    1. 分别说出强引用/软引用/弱引用/虚引用以及终结器引用
  2. 答案:

  1. 强引用:JVM默认引用关系就是强引用,只要存在强引用,对象就不会被回收。
  2. 软引用:和强引用类似,区别是当垃圾回收时,程序的内存不足,就会将软引用进行回收。
    1. 例如:缓存对象
  3. 弱引用:当垃圾回收时,不管内存够不够都会回收。
  4. 虚引用:当对象被垃圾回收器回收时,可以接收到对应的通知
  5. 终结器对象:当对象要被回收时,会把对象放入finalizer类中的引用队列中,做收尾工作。
  6. 总结:

ThreadLocal中为什么要使用弱引用

有哪些常见的垃圾回收算法

  1. 回答思路:
    1. 说出4个垃圾回收机制
    2. 优缺点
  2. 答案:

  1. 标记清除:
    1. 给对象添加一个属性,没有被引用的值为0,直接清除
    2. 缺点:会产生内存碎片,浪费空间
  2. 标记整理:
    1. 将被引用的对象标记并移动到内存的另一侧后,在将前一测清除。
  3. 复制
    1. 将内存分为两块,from和to,存在引用的放入to中,清除from,最后将from和to名称调换。
      1. 优点:吞吐量高,没有内存碎片
      2. 内存使用率低
  4. 分代GC
    1. 分为年轻代(包含eden区和s0和s1)和老年代。
      1. s1和s0模拟的是复制算法
  1. 总结

有哪些常用的垃圾回收器

  1. 总结:

如何解决内存泄露的问题

  1. 回答思路
    1. 解释名称:内存泄露和内存溢出
    2. 提出解决内存泄露的思路
    3. 可以用的工具
  2. 答案

  1. 内存泄露是:当Java不在使用该对象,但是该对象仍然在GC Root链上,不可被回收。
  2. 解决步骤:

常见的JVM参数

  1. -Xmx(最大堆内存)和-Xms(最小堆内存)
  1. -XX MaxMetaspaceSizze和 -Xss
  1. -Xmn(年轻代大小)
  1. 打印GC日志
  1. 总结:

====================================================== 我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1ic6i2j5b0j

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-09-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是JVM
  • 字节码文件的组成
  • 聊一聊运行时数据区
  • 说一说在哪些区域会出现内存溢出,会有什么现象?
  • JVM在jdk6~8之间在内存区域有什么不同?
  • 类的生命周期
  • 什么是类加载器
  • 什么是双亲委派机制
  • 如何打破双亲委派机制
  • 如何判断堆上的对象没有被引用
  • JVM中都有哪些引用类型
  • ThreadLocal中为什么要使用弱引用
  • 有哪些常见的垃圾回收算法
  • 有哪些常用的垃圾回收器
  • 如何解决内存泄露的问题
  • 常见的JVM参数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档