《面试实录》 携程二面,JVM底层剖析

小龙coding
  • 对线面试官
  • 面试实录
  • Java
  • Java
  • JVM
大约 7 分钟

本期是【面试实录】系列文章的第 4 期,持续更新中.....。

  • 欢迎关注+订阅,持续更新中!!!致力打造校招核心面试攻略~
  • 根据秋招春招上岸大厂面试经历以及身边朋友上岸面试录音模拟面试现场,并整合面试常考知识点,通俗有趣的去讲解 "八股文",不一样的系列,轻松掌握知识~

面试实录】专栏系列目前已经连载 4 篇了,据说看了这个系列的朋友都拿到了大厂offer~

考点速查

本期会通过面试模拟探讨 JVM 高频相关问题,涉及 基础知识 与 项目场景问题分析与处理

本期题改编自 ——2023届秋招补录 携程后端 二面

面试现场

叮叮叮......

面试官:“你好,我是XX面试官,请问是小龙吗?”

小龙:“您好,面试官,我是小龙”

面试官:“好的,现在有空吗,我们开始面试吧”

小龙:“嗯嗯,准备好啦”

.......

other questions

.......

面试官:"我看你简历写熟悉 JVM 相关,我们先问几个基础,然后再结合具体问题分析一下即可。"

小龙:"好的。"

面试官:"Ok,能给我讲讲 Java为什么被称为平台无关性语言吗?"

小龙:"这个很好理解,其实 Java 跨平台主要就是靠 JVM,我们在不同操作系统安装不同的 JVM ,JVM屏蔽了所以操作平台信息,它只管将按照统一标准生成的字节码文件(Java源码经javac编译后生成的文件)拿来执行。便实现了一次编译,处处执行的效果。"

面试官:"你了解 JVM 里面的垃圾回收吗?说说为什么要进行垃圾回收?"

小龙:"因为我们的内存空间是有限且宝贵的,当程序不再需要某些对象,也就是出现了“没用的东西”,如果不对这些无用东西进行处理便会白白占用内存。因此我们需要进行垃圾回收,释放它们占用的内存,以便生成有用的新对象。"

小龙:"简单一句话,就是回收内存,以便后续新对象产生有足够空间。"

面试官:"那它是怎样判断对象是否是垃圾的呢?"

小龙:"其实无论什么方法,JVM 判断对象为垃圾的方法就是看这个对象是否还存在引用。"

小龙:"这里有两种方法,一种是引用计数法,它是为对象添加一个引用计数器,当对象有一个引用,计数器便加1,反之亦然,当减为0时便没有引用,判断为垃圾。"

小龙:"不过这种方法会有局限,就是有两个对象,其实它们已经没用啦,本该回收,但是这两个对象却互相引用,这时就无法被判定为垃圾啦。"

面试官:"那 JVM 是采用什么办法解决的呢?"

小龙:"它采用一种叫 可达性分析法 来判定。这种是通过从一系列被称为 “GC Roots”的对象作为起点开始搜索,如果到该对象不可达,那么该对象就是垃圾。简单一句话,就是 从 GC Roots 到该对象可达。"

面试官:"那么何为 GC Roots 呢?"

小龙:"比如,Java虚拟机栈(栈帧中的本变量表)中引用的对象,方法区常量、静态变量引用的对象,本地方法栈 JNI 引用对象,所有被同步锁持有的对象这些。"

面试官:"OK,看来基础还是不错。那我们不谈基础,这个感觉网上随便搜搜背背到处都有。我们结合具体问题谈谈哈。"

面试官:"假如 CPU 使用率持续飙升,你怎样排查?从代码和 JVM层面讲解一下,毕竟不是个个都是资深程序员,我们平时可能还是更多关心代码层面。"

独白:"这个面试官不按套路出牌,想必网上那套 根据 JVM 一系列命令的老八股肯定不行。幸好我对于这些问题在【面试笔记】都有自己独到的见解"`

小龙:"对于这个问题,如果真正发生在项目中,因为在真实项目涉及的范围都很广,我们要考虑的地方也很多,我觉得我们第一件事不是盲目排查,要先通过一系列手段和工具进行信息收集。"

小龙:"不过,在公司里面,假如刚发布上线,部署的机器便出现 CPU 飙升,此时我们应该先进行回滚,然后再进问题分析解决。"

小龙:"事发时我们可以先看各个指标(CPU、内存、网络、磁盘)信息,方便对全局有更好的把握和判断。"

小龙:"然后我们对监控日志分析,首先查看故障时间点的应用日志,看有没有大量耗时操作,如果有耗时的方法我们可以重新 review 一下方法实现,看有无大量数据处理,有无锁争用等。"

小龙:"如果想要简单看代码的话,我们还可以考虑进行 Code Review,直接从代码层面分析,当然个人感觉这种效率很低,如果是浅显的错误可以通过以上很快就发现问题,但是如果涉及内部逻辑复杂一点,借助 JDK 的一些命令和工具可能效率更高。"

面试官:"嗯嗯,具体怎样做呢?"

独白:"很顺理成章回到老八股~"

小龙:"我们可以分析GC日志,获取线程转储并分析,获取堆转储并分析。"

小龙:"详细做法可以 启动程序之前通过 HeapDumpOnOutOfMemoryError 和 HeapDumpPath 这两个参数开启堆内存异常日志,到时候会将日志输出到指定路径。"

小龙:"发现日志异常后,一般我们的服务部署在 Linux 上的,我们可以通过 top 命令查看进程 cpu使用率。"

小龙:"再通过 top -Hp pid 查看进程下所有具体线程占用系统资源情况,再通过 jstack pid 查看具体线程的堆栈信息(线程ID、状态(wait,sleep),是否持有锁),再通过 jmap 查看堆内存的使用情况 jmap -heap pid。"

小龙:"通过以上命令分析基本可以看出什么问题导致内存上升,现在分析问题产生的原因(或者可以直接借用工具 使用 jstat 查看监控 JVM 的内存和 GC 情况,观察问题大概出现在什么区域 )"

小龙:"然后我们在启动时,已经设置了 dump 文件,通过 MAT 打开 dump 的内存日志文件,分析即可。"

面试官:"我看你说使用Dump,内存Dump时有哪些注意事项呢?"

小龙:"根据实际情况来看,获取内存快照可能会让系统暂停或阻塞一段时间,根据内存量决定。 使用jmap时,如果指定 参数,则会触发一次FullGC,需要注意。"

面试官:"好的,除了刚才讨论的问题,你还碰到过哪些 JVM 相关的问题呢?"

独白:"对于这些以及每个问题的详解都总结在了【面试笔记】中。"

小龙:"还有比如GC问题,内存泄漏,内存溢出这些等等。"

面试官:"好的,其他也不问什么啦,基本网上都能找得到答案。主要想考察基础和思考能力"

独白:“不愧是我,真男人是也!【面试笔记】在手,大厂 offer 不愁。”

知识总结

本期我们通过面试模拟了JVM部分基础问题和高频场景问题。订阅+星标持续追更。

面试重点

如何判断对象是否是垃圾内存持续飙升如何解决?(尽量结合公司具体项目分析,别来就背)