JVM面试题及答案(2024版最全总结)

JVM面试题及答案(2024版最全总结)-mikechen

JVM面试题是Java面试经常考察的内容,下面给大家总结一份非常全面的JVM面试题及答案@mikechen

JVM是什么

JVM,全称是Java虚拟机,是Java编程语言的运行环境,它可以在不同的操作系统上运行Java程序。

Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码字节码。

如下图所示:

JVM面试题及答案(2024版最全总结)-mikechen
简单来说JVM是用来解析和运行Java程序的,它是Java平台的核心组件,提供了许多功能,例如垃圾回收、内存管理、安全性和线程管理等。

 

JVM内存模型

JVM内存模型的整体结构,如下图所示:

JVM面试题及答案(2024版最全总结)-mikechen

包含:JVM堆虚拟机栈程序计数器Java方法区本地方法栈

1.JVM堆(Heap)

它是Java虚拟机中最大的一块内存区域,用于存储对象实例和数组,堆是所有线程共享的,因此在多线程环境下需要注意并发访问的问题。

 

2.JVM方法区(Method Area)

它是所有线程共享的内存区域,用于存储已加载的类信息、常量、静态变量、即时编译器编译后的代码等。

方法区也称为永久代(PermGen),但在JDK8之后,永久代已被移除,被元空间(MetaSpace)所代替。

 

3.Java虚拟机栈(Java Virtual Machine Stacks)

用于存储方法的局部变量、操作数栈、动态链接、方法出口等信息。栈帧在方法执行结束后会被弹出。

 

4.程序计数器(Program Counter Register)

它是一块较小的内存区域,用于存储正在执行的Java虚拟机字节码指令的地址。

 

5.本地方法栈(Native Method Stacks)

它用于存储Java程序调用本地方法(Native Method)时的参数和返回值。

 

JVM垃圾回收算法

1.标记清除算法

如下图所示:

JVM面试题及答案(2024版最全总结)-mikechen

1.标记阶段

从程序的根对象开始,递归遍历所有可以到达的对象,并将它们标记为“可达”的对象。

 

2.清除阶段

遍历整个堆,将没有标记的对象,即未被标记为“可达”,视为垃圾并回收其占用的内存。

 

标记清除算法适用

标记清除算法适用于:存活对象较多的情况,比较适用于年老代。

 

2.复制算法

复制算法,如下图所示:

JVM面试题及答案(2024版最全总结)-mikechen

复制算法步骤,主要分为如下步骤:

第一步:标记出所有的存活对象

从根集合节点进行扫描,例如:线程栈中的对象、静态变量、寄存器中的指针等,标记出所有的存活对象,

 

第二步:复制对象到新内存

找出所有仍然存活的对象,并将这些存活的对象复制到一块儿新的内存,比如:上方图片下边的那一块儿绿色内存。

 

第三步:回收垃圾并被清除

当所有存活的对象都被复制到To区后,From区中的所有对象都可以被清除(图中上边的那一块儿内存)。

 

复制算法适合

复制算法适合存活对象较少的情况下比较高效,基本上98%的对象是”朝生夕死”的,存活下来的会很少,所以特别适合于新生代。

 

3.标记整理算法

如下图所示:
JVM面试题及答案(2024版最全总结)-mikechen

标记整理算法步骤,主要分为如下4个步骤:

  1. 遍历内存中的所有对象,标记出所有正在使用的对象。
  2. 将所有标记过的对象移动到内存的一端,形成一个连续的内存块,同时将这些对象的地址更新到新的位置上。
  3. 将内存块另一端的所有未标记对象删除,并将这些内存空间标记为可用。
  4. 更新所有指向移动对象的指针,使其指向新的地址。

 

标记整理算法适合

标记整理算法适合老年代进行垃圾收集,parallel Oldgc和Serial old收集器就是采用该算法进行回收的。

 

4.分代收集算法

分代收集算法就是目前虚拟机使用的回收算法,这种算法根据对象的存活周期的不同将内存划分成几块,新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。

 

JVM垃圾收集器

1.Serial串行收集器

Serial是一个新生代收集器,使用的是标记复制算法,Serial收集器是最基础也是历史最悠久的收集器。

如下图所示:

JVM面试题及答案(2024版最全总结)-mikechen

Serial串行收集器的主要特点是单线程收集,即只使用一个线程来完成垃圾收集工作,它使用标记复制算法进行垃圾回收。

 

2.Parallel并行收集器

Parallel并行收集器是在Serial收集器的基础上发展而来,如下图所示:

JVM面试题及答案(2024版最全总结)-mikechen

其主要特点是使用多个线程同时进行垃圾回收,从而提高垃圾回收的效率,它使用标记复制算法进行垃圾回收。

 

3.CMS收集器

CMS收集器,全称是Concurrent Mark Sweep,CMS收集器主要用于收集老年代的垃圾。

如下图所示:

JVM面试题及答案(2024版最全总结)-mikechen

相比于Serial和Parallel收集器,CMS收集器的主要特点是采用并发收集的方式,,采用的是标记清除算法

 

4.G1收集器

G1垃圾收集器全称是Garbage First,G1垃圾收集器采用的是分代收集的思想。

如下图所示:

JVM面试题及答案(2024版最全总结)-mikechen

它将整个Java堆内存划分为多个大小相等的区域(Region),每个区域可以是年轻代,也可以是老年代。

G1收集器的阶段分以下几个步骤:

JVM面试题及答案(2024版最全总结)-mikechen

5.ZGC垃圾收集器

ZGC也称为The Z Garbage Collector,ZGC垃圾收集器是JDK 11中推出的一款追求极致低延迟的性质的JVM垃圾收集器

JVM面试题及答案(2024版最全总结)-mikechen

与CMS中的ParNew和G1类似,ZGC也采用标记复制算法,不过ZGC对该算法做了重大改进。

 

6.Shenandoah垃圾收集器

Shenandoah垃圾收集器于JDK 12中首次引入,主要针对需要大内存和低延迟的应用场景。

 

JVM调优参数

以下是重要的JVM调优参数:

JVM面试题及答案(2024版最全总结)-mikechen

1.指定JVM的初始内存和最大内存

参数:

-Xms和-Xmx

示例:

-Xms512m -Xmx2g

指定JVM的初始内存为512MB,最大内存为2GB。

 

2.设置新生代的内存大小

参数:

-Xmn

示例:

-Xmn2g

Xmn2g:设置年轻代大小为2G。

 

3.指定持久代的初始大小和最大大小

参数:

-XX:PermSize和-XX:MaxPermSize

示例:

-XX:PermSize=128m -XX:MaxPermSize=256m

指定持久代的初始大小为128MB,最大大小为256MB。

 

4.启用G1垃圾收集器

参数:

-XX:+UseG1GC

示例:

java -XX:+UseG1GC Main

启用G1垃圾收集器。

 

5.启用CMS垃圾收集器

参数:

-XX:+UseConcMarkSweepGC

UseConcMarkSweepGC,表示启用CMS垃圾收集器。

 

6.打印垃圾收集器的详细信息和时间戳

参数:

-XX:+PrintGCDetails

参数:

-XX:+PrintGCDetails -XX:+PrintGCDateStamps

打印垃圾收集器的详细信息和时间戳。

 

7.调整新生代和老年代的比例

参数:

-XX:NewRatio=2

NewRatio=2表示新生代和老年代的比例为1:2。

 

8.调整Eden区和Survivor区的比例

参数:

-XX:SurvivorRatio=8

SurvivorRatio=8表示Eden区和Survivor区的比例为8:1。

 

JVM性能调优

JVM面试题及答案(2024版最全总结)-mikechen

JVM性能调优主要包含以下方法,大概分为5个步骤:

1.监控GC的状态

使用各种JVM调优工具,查看当前日志,分析当前JVM调优参数设置,并且分析当前堆内存快照和gc日志。

根据实际的各区域内存划分和GC执行时间,觉得是否进行优化。

举一个例子: 系统崩溃前的一些现象:

  •  每次垃圾回收的时间越来越长;
  •  FullGC的次数越来越多;
  • 逐渐到达OutOfMemoryError的临界值;

这个时候就需要分析JVM内存快照dump。

2.生成堆的dump文件

可以通过Java的jmap命令来生成该文件,需要分析dump文件。

 

3.分析dump文件

打开这个3G的堆信息文件,显然一般的Window系统没有这么大的内存,必须借助高配置的Linux,几种工具打开该文件:

  •  Visual VM;
  •  MAT;
  •  JDK 自带的Hprof工具等;

文件太大,建议使用Eclipse专门的静态内存分析工具Mat打开分析。

 

4.分析和调整

这里会涉及到如下内容:

  • 调整垃圾回收机制,提高垃圾回收效率,避免长时间的停顿;
  • 调整线程池大小,避免线程过多导致的性能下降;
  • 优化代码,减少不必要的对象创建和内存占用等。

 

5.不断的试验和试错

最后,就需要通过不断的试验和试错,分析并找到最合适的参数,并则将这些参数应用到所有服务器。

以上就是JVM面试题及答案详解,更多JVM内容请查看:JVM(Java虚拟机)从0到1全部合集

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复架构,即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法