JVM基础面试题库
1.JVM中的垃圾收集器有哪些,它们的工作原理是什么?
JVM中的垃圾收集器主要包括以下几种:
1、 Serial收集器:它是一个单线程收集器,工作时会暂停所有其他工作线程("Stop-The-World"),它的优点是简单高效(与其他收集器的单线程比),适用于单核处理器的环境。
2、 ParNew收集器:可以看作是Serial收集器的多线程版本,主要用于新生代的垃圾收集,适合多核处理器环境。
3、 Parallel Scavenge收集器:也是一个新生代垃圾收集器,使用多线程收集,注重吞吐量(CPU用于运行用户代码的时间比率)。
4、 Serial Old收集器:是Serial收集器的老年代版本,单线程,采用标记-整理算法。
5、 Parallel Old收集器:是Parallel Scavenge收集器的老年代版本,使用多线程并行收集,目标是提高系统吞吐量。
6、 CMS(Concurrent Mark Sweep)收集器:以获取最短回收停顿时间为目标,使用多线程并发标记和清除算法。
7、 G1(Garbage-First)收集器:采用分区堆(Heap)和增量式垃圾回收,目标是兼顾吞吐量和停顿时间。
2.JVM中的类加载器有哪些,它们各自的作用是什么?
JVM中的类加载器主要有三种:
1、启动类加载器(BootstrapClassLoader) :它负责加载存放在<JAVA_HOME>/jre/lib目录中,或者被-Xbootclasspath参数指定的路径中的类库。
2、扩展类加载器(Extension ClassLoader) :它负责加载<JAVA_HOME>/jre/lib/ext目录中的类库。
3、应用程序类加载器(Application ClassLoader) :它负责加载用户类路径(Classpath)上所指定的类库。
每个类加载器都有其特定的加载范围,这种层次关系保证了Java程序稳定运行。
3.JVM中垃圾回收的算法有哪些?
JVM垃圾回收的主要算法包括:
1、标记-清除算法(Mark-Sweep) :先标记出所有需要回收的对象,然后统一清除这些对象。
2、复制算法(Copying) :将内存分为两块,每次只使用其中一块,当这一块的内存用完了,就把还活着的对象复制到另一块上去。
3、标记-整理算法(Mark-Compact) :类似于标记-清除算法,但在清除后会进行内存整理,减少碎片。
4、分代收集算法(Generational Collection) :根据对象存活周期的不同将内存划分为几块,如年轻代、老年代等,采用适合各个年代的收集算法。
4.JVM如何判断对象是否死亡?
JVM判断对象是否死亡主要有两种方式:
1、引用计数法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
2、可达性分析:通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
5.JVM中有哪些引用类型?
JVM中主要有四种引用类型:
1、强引用(Strong Reference) :普通的对象引用,只要强引用还存在,垃圾回收器永远不会回收掉被引用的对象。
2、软引用(Soft Reference) :内存不足时,会被垃圾回收器回收掉。
3、弱引用(Weak Reference) :只能生存到下一次垃圾收集之前,当垃圾回收器工作时,无论内存是否足够,都会回收掉只被弱引用关联的对象。
4、虚引用(Phantom Reference) :最弱的一种引用关系,无法通过虚引用来获取对象实例,它的存在仅仅是为了在这个对象被收集器回收时收到一个系统通知。
6.JVM的永久代(PermGen)和元空间(Metaspace)有什么区别?
永久代(PermGen)和元空间(Metaspace)是JVM中存储类元数据的区域,二者的主要区别如下:
1、存储位置:永久代是在JVM的堆内存中,而元空间位于本地内存。
2、大小限制:永久代的大小是固定的,容易出现内存溢出;元空间利用本地内存,所以默认情况下只受本地内存大小限制。
3、回收机制:永久代的回收主要针对常量池的回收和对类型的卸载;元空间提供了更好的性能,在使用本地内存的同时,减少了垃圾收集的频率。
7.JVM中的堆和栈有什么区别?
堆和栈是JVM中两个重要的内存区域,它们的主要区别如下:
1、用途:堆用于存储对象实例和数组,是垃圾回收的主要区域;栈用于存储局部变量、操作数栈和控制流。
2、线程共享性:堆是被所有线程共享的内存区域,而栈是线程私有的。
3、内存分配:堆的内存分配是动态的,适用于动态对象的存储;栈的内存分配是连续的,适用于临时变量的存储。
4、内存回收:堆的内存回收由垃圾回收器处理,栈的内存分配和回收是自动的。
8.JVM中Full GC触发的原因有哪些?
Full GC触发的原因主要有以下几点:
1、老年代空间不足:老年代存放长期存活的对象,当老年代空间不足时,会触发Full GC。
2、永久代或元空间不足:当存储类元数据的区域空间不足时,同样会触发Full GC。
3、System.gc()调用:系统调用System.gc()时,通常会触发Full GC。
4、JVM参数:由于某些JVM参数设置不当,如过小的堆空间,也可能触发Full GC。
5、Eden区、Survivor区向老年代晋升失败:如果Eden区或Survivor区中的对象在Minor GC后仍然存活,并且老年代无法容纳这些对象,也会触发Full GC。
9.JVM中的类加载器有哪些,它们各自的作用是什么?
JVM中的类加载器主要有以下几种:
1、启动类加载器(Bootstrap ClassLoader): 加载Java的核心库(JAVA_HOME/jre/lib/rt.jar等),是所有类加载器的父加载器。
2、扩展类加载器(Extension ClassLoader): 加载JAVA_HOME/jre/lib/ext目录中或者由java.ext.dirs系统属性指定的路径中的类库。
3、应用程序类加载器(Application ClassLoader): 加载用户类路径(Classpath)上的类库,如果应用中没有定义自己的类加载器,这将是默认的类加载器。
每个类加载器都有自己的职责范围,确保Java应用能够加载类的灵活性和安全性。
10.JVM内存区域划分及其作用是什么?
JVM的内存区域主要包括:
1、方法区(Method Area): 存储类信息、常量、静态变量等。
2、堆(Heap): 存放对象实例,是垃圾收集器管理的主要区域。
3、栈(Stack): 存放方法的局部变量表、操作数栈、动态链接等信息。
4、程序计数器(Program Counter Register): 当前线程所执行的字节码的行号指示器。
5、本地方法栈(Native Method Stack): 为Native方法服务。
这些区域各司其职,共同支持了Java程序的运行。
11.JVM中垃圾收集的算法有哪些?
JVM垃圾收集的主要算法包括:
1、标记-清除算法(Mark-Sweep): 标记出所有需要回收的对象,然后统一回收这些对象。
2、复制算法(Copying): 将内存分为两块,每次只使用其中一块,垃圾收集时将活动对象复制到另一块上。
3、标记-整理算法(Mark-Compact): 标记过程与标记-清除算法相同,但后续步骤是将所有存活的对象向一端移动,然后清理掉端边界以外的内存。
4、分代收集算法(Generational Collection): 根据对象存活周期的不同将内存划分为几块,比如年轻代、老年代等,各个年代使用不同的垃圾收集算法。
这些算法各有优劣,JVM根据具体情况选择合适的算法或算法组合进行垃圾回收。
12.JVM中的双亲委派模型。
JVM中的双亲委派模型是类加载器的一种工作机制,其主要特点如下:
1、工作流程: 当一个类加载器尝试加载某个类时,它首先不会尝试自己去加载这个类,而是把这个请求委托给父类加载器去完成,依次递归,如果父加载器无法完成这个加载(比如它的搜索范围中没有这个类),子加载器才会尝试自己去加载这个类。
2、优点: 这个模型可以避免类的重复加载,保护程序安全防止核心API被随意篡改。
3、破坏双亲委派: 在某些情况下,比如SPI(Service Provider Interface)服务,类加载器需要破坏双亲委派模型以便于服务提供者能够提供接口实现。
13.JVM中的永久代(PermGen)和元空间(Metaspace)有何区别?
永久代(PermGen)和元空间(Metaspace)是JVM内存的两个不同部分:
1、永久代(PermGen): 在JVM早期版本中,用于存储类的元数据、字符串常量等。它有固定的大小,容易发生OutOfMemoryError。
2、元空间(Metaspace): 在Java 8中,永久代被元空间所替代。元空间使用本地内存,存储类的元数据。相比永久代,它的大小受物理内存的限制,更加灵活。
3、性能优化: 元空间的引入减少了垃圾收集的频率,提升了性能,尤其是在加载大量类的应用中。
14.JVM优化的常见手段有哪些?
JVM优化通常涉及以下几个方面:
1、调整堆大小: 适当增加JVM堆的大小可以减少垃圾收集的频率,但过大的堆可能会增加垃圾收集的时间。
2、选择合适的垃圾收集器: 根据应用的特点选择最合适的垃圾收集器,如G1、CMS等。
3、线程堆栈大小(-Xss): 适当的线程堆栈大小可以减少内存的使用,但太小可能会导致栈溢出。
4、分析并优化代码: 优化应用代码,减少内存泄漏和不必要的对象创建。
5、JVM参数调优: 通过调整JVM启动参数,优化JVM的性能。
6、使用性能分析工具: 利用JProfiler、MAT、VisualVM等工具分析性能问题。
15.JVM中的Just-In-Time(JIT)编译器。
JVM中的Just-In-Time(JIT)编译器是一种提高程序运行效率的机制,其工作原理如下:
1、编译时机: JIT编译器在运行时将字节码转换为本地机器码,而非在程序运行之前。
2、优化代码: JIT编译器可以根据运行时的数据和行为对代码进行优化。
3、提升性能: JIT编译可以显著提高Java程序的性能,减少程序运行时间。
4、适应性: JIT编译器可以适应程序的运行特性,进行动态优化。
查看17道真题和解析