JVM面试真题总结(七)
文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/
文章收录在网站:http://hardyfish.top/
解释GC的引用计数算法及其局限性
引用计数算法是一种非常直观、简单的垃圾收集算法。
它的基本思想是:
- 对于一个对象,如果没有其他对象引用它,那么这个对象就是不再使用的
- 因此就可以被当作垃圾收集掉。
具体来说,引用计数算法为每个对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1
当引用失效时,计数器值就减1。
- 任何时候,只要对象的引用计数器为0,那么这个对象就是不再使用的,可以被回收。
引用计数算法的主要优点是:
- 它的实现简单,而且垃圾对象可以在它成为垃圾的那一刻就被立即回收,这使得程序的内存使用更加及时和高效。
然而,引用计数算法也有一些重要的缺点:
无法处理循环引用
- 如果两个对象互相引用,但没有其他对象引用它们,那么这两个对象实际上是垃圾
- 但它们的引用计数都不为0,因此无法被回收。
计数器的维护开销大:
- 每次引用关系改变时,都需要更新计数器,这会消耗一定的计算资源。
无法进行有效的内存整理:
- 引用计数算法只是简单地回收垃圾对象,而不能像其他GC算法那样
- 通过移动对象来整理内存,避免内存碎片的产生。
列举并解释常见的垃圾收集算法
垃圾收集(
Garbage Collection,GC
)是自动内存管理的重要部分常用的垃圾回收算法主要有以下几种:
标记-清除(Mark-Sweep)算法:
- 这是最基础的垃圾收集算法。
- 它分为标记和清除两个阶段,首先标记出所有需要回收的对象,然后清除被标记的对象。
- 这种算法的主要缺点是清除后会产生大量不连续的内存碎片。
复制(Copying)算法:
- 这种算法将可用内存分为两个相等的区域,每次只使用其中一个区域。
- 垃圾收集时,会遍历当前使用区域中的所有对象,把还活着的对象复制到另一个区域中,然后把当前使用区域整个清空。
- 这种算法的优点是没有内存碎片,缺点是需要两倍内存空间。
标记-整理(Mark-Compact)算法:
- 这种算法是标记-清除算法的改进版,增加了整理的过程。
- 在标记和清除之后,会把所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
- 这种算法避免了内存碎片,但移动对象的成本比较高。
分代(Generational)收集算法:
- 这种算法基于这样一个观察:大部分对象都是生命周期短的,少部分对象的生命周期长。
- 所以,内存被分为两部分,一部分为新生代,一部分为老年代。
- 新对象首先在新生代中分配,新生代满了之后进行一次垃圾收集。
- 存活的对象会被复制到老年代中,老年代满了之后,再对老年代进行垃圾收集。
在ZGC和G1之间应如何做出选择?
ZGC和G1都是高级的垃圾收集器,为了满足大内存和低延迟的需求而设计。
但它们的设计理念和实现方式有所不同,因此在选择时,需要考虑以下几个方面:
延迟
- 如果你的应用对延迟非常敏感,那么ZGC可能是更好的选择。
- ZGC的设计目标是将所有的GC停顿时间控制在10毫秒以内,而且这个时间不会随着堆大小的增加而增加。
内存大小:
- 如果你的应用需要处理大量的数据,或者你的系统有大量的可用内存,那么ZGC可能是更好的选择。
- ZGC可以处理多达4TB的堆内存。
CPU资源:
- ZGC为了实现低延迟和高吞吐量,会使用更多的CPU资源。
- 如果你的系统CPU资源有限,那么G1可能是更好的选择。
平台支持:
- 目前,ZGC只在
Linux/x64
平台上可用,并且需要启用JVM的实验性功能。- 如果你的环境不满足这些要求,那么你只能选择G1或其他垃圾收集器。
长期支持:
- G1从JDK 9开始已经成为默认的垃圾收集器,而ZGC仍然是一个实验性的特性。
- 如果你需要长期的稳定性和支持,那么G1可能是更好的选择。
G1垃圾收集器的优缺点分别是什么?
G1(Garbage-First
)垃圾收集器是一种面向服务器的垃圾收集器它具有以下优点和缺点:
优点:
可预测的停顿时间:
- 这是G1最主要的优点,也是它的设计目标之一。
- G1收集器允许用户指定期望的停顿时间目标,G1会尽可能地在这个时间范围内完成垃圾收集。
高吞吐量:
- G1能充分利用多CPU、多核硬件的优势,提高垃圾收集的吞吐量。
避免内存碎片:
- G1通过将堆划分为许多小的区域,并优先回收垃圾最多的区域,从而有效地减少了内存碎片。
大内存处理能力:
- G1可以处理堆大小从几百MB到多达4TB的应用。
缺点:
CPU资源占用:
- G1在进行并发阶段时,会占用一部分CPU资源
- 对于CPU资源紧张的系统,这可能会对应用程序的性能产生影响。
需要更多的内存开销:
- 由于G1将堆划分为许多小的区域
- 这会导致相比其他垃圾收集器,G1需要更多的内存开销。
在某些情况下,G1可能无法达到预设的停顿时间目标。
例如,如果堆中的存活对象非常多,或者垃圾收集线程的数量设置得过少
- 都可能使得G1无法在预设的时间内完成垃圾收集。