239 Star 2.1K Fork 87

鹏磊 / DevBooks

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Jvm最新2021年面试题附答案解析,大汇总.md 10.29 KB
一键复制 编辑 原始数据 按行查看 历史

Jvm最新2023年面试题附答案解析,大汇总

全部答案,更新日期:2023年6月11日,直接下载吧!

下载链接:高清172份,累计 7701 页大厂面试题 PDF

1、ZGC 了解吗?

JDK11 中加入的具有实验性质的低延迟垃圾收集器,目标是尽可能在不影响吞吐量的前提下,实现在任意堆内存大小都可以把停顿时间限制在 10ms 以内的低延迟。

基于 Region 内存布局,不设分代,使用了读屏障、染色指针和内存多重映射等技术实现可并发的标记-整理,以低延迟为首要目标。

ZGC 的 Region 具有动态性,是动态创建和销毁的,并且容量大小也是动态变化的。

2、safepoint是什么?

STW并不会只发生在内存回收的时候。现在程序员这么卷,碰到几次safepoint的问题几率也是比较大的。

当发生GC时,用户线程必须全部停下来,才可以进行垃圾回收,这个状态我们可以认为JVM是安全的(safe),整个堆的状态是稳定的。

如果在GC前,有线程迟迟进入不了safepoint,那么整个JVM都在等待这个阻塞的线程,造成了整体GC的时间变长。

3、JVM 提供的常用工具

jps:

用来显示本地的 Java 进程,可以查看本地运行着几个 Java 程序,并显示他们的进程号。 命令格式:jps

jinfo:

运行环境参数:Java System 属性和 JVM 命令行参数,Java class path 等信息。 命令格式:jinfo 进程 pid

jstat:

监视虚拟机各种运行状态信息的命令行工具。 命令格式:jstat -gc 123 250 20

jstack:

可以观察到 JVM 中当前所有线程的运行情况和线程当前状态。 命令格式:jstack 进程 pid

jmap:

观察运行中的 JVM 物理内存的占用情况(如:产生哪些对象,及其数量)。 命令格式:jmap [option] pid

4、CMS 收集器(多线程标记清除算法)

Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾回收停顿时间, 和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验。CMS 工作机制相比其他的垃圾收集器来说更复杂。整个过程分为以下 4 个阶段:

初始标记

只是标记一下 GC Roots 能直接关联的对象,速度很快,仍然需要暂停所有的工作线程。

并发标记

进行 GC Roots 跟踪的过程,和用户线程一起工作,不需要暂停工作线程。

重新标记

为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,仍然需要暂停所有的工作线程。

并发清除

清除 GC Roots 不可达对象,和用户线程一起工作,不需要暂停工作线程。由于耗时最长的并发标记和并发清除过程中,垃圾收集线程可以和用户现在一起并发工作, 所以总体上来看CMS 收集器的内存回收和用户线程是一起并发地执行。

5、对象都是优先分配在年轻代上的吗?

不是。当新生代内存不够时,老年代分配担保。而大对象则是直接在老年代分配。

6、有哪些 GC 算法?

标记-清除算法

分为标记和清除阶段,首先从每个 GC Roots 出发依次标记有引用关系的对象,最后清除没有标记的对象。

执行效率不稳定,如果堆包含大量对象且大部分需要回收,必须进行大量标记清除,导致效率随对象数量增长而降低。

存在内存空间碎片化问题,会产生大量不连续的内存碎片,导致以后需要分配大对象时容易触发 Full GC。

标记-复制算法

为了解决内存碎片问题,将可用内存按容量划分为大小相等的两块,每次只使用其中一块。当使用的这块空间用完了,就将存活对象复制到另一块,再把已使用过的内存空间一次清理掉。主要用于进行新生代。

实现简单、运行高效,解决了内存碎片问题。代价是可用内存缩小为原来的一半,浪费空间。

HotSpot 把新生代划分为一块较大的 Eden 和两块较小的 Survivor,每次分配内存只使用 Eden 和其中一块 Survivor。垃圾收集时将 Eden 和 Survivor 中仍然存活的对象一次性复制到另一块 Survivor 上,然后直接清理掉 Eden 和已用过的那块 Survivor。HotSpot 默认Eden 和 Survivor 的大小比例是 8:1,即每次新生代中可用空间为整个新生代的 90%。

标记-整理算法

标记-复制算法在对象存活率高时要进行较多复制操作,效率低。如果不想浪费空间,就需要有额外空间分配担保,应对被使用内存中所有对象都存活的极端情况,所以老年代一般不使用此算法。

老年代使用标记-整理算法,标记过程与标记-清除算法一样,但不直接清理可回收对象,而是让所有存活对象都向内存空间一端移动,然后清理掉边界以外的内存。

标记-清除与标记-整理的差异在于前者是一种非移动式算法而后者是移动式的。如果移动存活对象,尤其是在老年代这种每次回收都有大量对象存活的区域,是一种极为负重的操作,而且移动必须全程暂停用户线程。如果不移动对象就会导致空间碎片问题,只能依赖更复杂的内存分配器和访问器解决。

7、有什么堆外内存的排查思路?

进程占用的内存,可以使用top命令,看RES段占用的值。如果这个值大大超出我们设定的最大堆内存,则证明堆外内存占用了很大的区域。

使用gdb可以将物理内存dump下来,通常能看到里面的内容。更加复杂的分析可以使用perf工具,或者谷歌开源的gperftools。那些申请内存最多的native函数,很容易就可以找到。

8、SWAP会影响性能么?

当操作系统内存不足的时候,会将部分数据写入到SWAP交换分中,但是SWAP的性能是比较低的。如果应用的访问量较大,需要频繁申请和销毁内存,就容易发生卡顿。一般高并发场景下,会禁用SWAP。

9、你知道哪些JVM性能调优

设定堆内存大小

1、 -Xmx:堆内存最大限制。设定新生代大小。新生代不宜太小,否则会有大量对象涌入老年代

2、 -XX:NewSize:新生代大小

3、 -XX:NewRatio 新生代和老生代占比

4、 -XX:SurvivorRatio:伊甸园空间和幸存者空间的占比

5、 设定垃圾回收器 年轻代用 -XX:+UseParNewGC 年老代用-XX:+UseConcMarkSweepGC

10、你都有哪些手段用来排查内存溢出?

(这个话题很大,可以从实践环节中随便摘一个进行总结,下面举例一个最普通的)

你可以来一个中规中矩的回

内存溢出包含很多种情况,我在平常工作中遇到最多的就是堆溢出。有一次线上遇到故障,重新启动后,使用jstat命令,发现Old区在一直增长。我使用jmap命令,导出了一份线上堆栈,然后使用MAT进行分析。通过对GC Roots的分析,我发现了一个非常大的HashMap对象,这个原本是有位同学做缓存用的,但是一个无界缓存,造成了堆内存占用一直上升。后来,将这个缓存改成 guava的Cache,并设置了弱引用,故障就消失了。

这个回答不是十分出彩,但着实是常见问题,让人挑不出毛病。

11、JIT是什么?

12、Java 中堆和栈有什么区别?

13、方法区

14、你能保证 GC 执行吗?

15、说说G1垃圾收集器的工作原理

16、方法区的作用是什么?

17、ParNew 垃圾收集器(Serial+多线程)

18、你知道哪些内存分配与回收策略?

19、什么是栈

20、Minor Gc和Full GC 有什么不同呢?

21、JVM怎么判断一个对象是不是要回收?

22、说一下Java对象的创建过程

23、怎么看死锁的线程?

24、JVM垃圾回收机制,何时触发MinorGC等操作

25、GC垃圾回收算法与垃圾收集器的关系?

26、永久代

27、谈谈JVM中,对类加载器的认识

28、描述一下什么情况下,对象会从年轻代进入老年代

29、可达性分析

30、描述一下JVM加载class文件的原理机制?

31、描述一下 JVM 加载 class 文件的原理机制

全部答案,更新日期:2023年6月11日,直接下载吧!

下载链接:全部答案,整理好了

新增:高清PDF:172份,7701页,最新整理

Java
1
https://gitee.com/souyunku/DevBooks.git
git@gitee.com:souyunku/DevBooks.git
souyunku
DevBooks
DevBooks
master

搜索帮助