先有JVM还是先有垃圾回收器?

简介: 是先有垃圾回收器再有JVM呢,还是先有JVM再有垃圾回收器呢?或者是先有垃圾回收再有JVM呢?历史上还真是垃圾回收更早面世,先有垃圾回收再有JVM。下面我们就来刨析刨析JVM的垃圾回收~

是先有垃圾回收器再有JVM呢,还是先有JVM再有垃圾回收器呢?或者是先有垃圾回收再有JVM呢?历史上还真是垃圾回收更早面世,垃圾回收最早起源于1960年诞生的LISP语言,Java只是支持垃圾回收的其中一种。下面我们就来刨析刨析JVM的垃圾回收~

在这里插入图片描述

1. 判断可回收对象

1.1 引用计数法

面试官:JVM为什么不采用引用计数法?

每个Java对象在引用计数法里都有一个引用计数器,引用失效则计数器 - 1,有新的引用则计数器 + 1,通过计数器的数值来判断该对象是否是可回收对象。

大家看下这个例子,如果对象A和对象B没有被任何对象引用,也没有被任何线程访问,这两个对象按理应该被回收。但如果对象A的成员变量引用了对象B,对象B的成员变量引用了对象A,它们的引用计数器数值都不为0,通过引用计数法并不能将其视为垃圾对象。

    class A {
   
   
        B b = new B();
    }
    class B {
   
   
        A a = new A();
    }

就因为引用计数法很难解决对象之间相互循环引用的问题,所以目前JVM采用可达性分析算法来判断Java对象是否是可回收对象。

1.2 可达性分析算法

面试官:那可达性分析算法是什么?

可达性分析顾名思义就是以某个起始点来判断它是否可达,这个起始点称为GC Roots。如果Java对象不能从GC Roots作为起始点往下搜索到,那该对象就被视为垃圾对象,即可回收对象。

在这里插入图片描述

可以作为GC Roots对象一共包括以下四种,这点也是面试官常问的:

  1. 虚拟机栈中引用的对象。
  2. 本地方法栈中引用的对象。
  3. 方法区中类静态属性引用的对象。
  4. 方法区中常量引用的对象。

2. 垃圾回收器

2.1 垃圾回收区域

面试官:垃圾回收器回收的是哪个区域?

JVM由五大区域组成:堆内存、方法区、程序计数器、虚拟机栈、本地方法栈。先说结论,垃圾回收器回收的是堆内存和方法区两大区域。

程序计数器、虚拟机栈、本地方法栈的内存分配和回收都具备确定性,都是随着线程销毁而销毁,因此不需要进行回收

但在堆内存、方法区中,内存分配和回收都是动态的,我们只有在运行期间才能知道会创建哪些对象;另外这些垃圾对象不会自动销毁,如果任由这两部分区域的垃圾对象不管,势必造成内存的浪费甚至有内存泄漏的可能。

垃圾回收器存在的意义就是通过自动检测和回收这些垃圾对象,来减少内存泄漏的风险。

2.2 回收永久代

面试官:永久代会不会进行垃圾回收?

虽然永久代的垃圾回收效率是比较低的,但永久代里的废弃常量和无用的类仍然会被回收。

例如创建一个字符串常量name,该字符串会存在于常量池中。如果该字符串没有任何String对象去引用它,当发生内存回收时有必要会清除该废弃常量。

private static final String name = "JavaGetOffer";

2.3 垃圾回收器

面试官:你说说都有哪些垃圾回收器?

目前市面上共有七种垃圾回收器。

  1. Serial是一个作用在新生代单线程垃圾回收器。在垃圾回收期间系统的所有线程都会阻塞,因此垃圾回收效率也相对较高

  2. ParNew则是Serial的多线程版本。这也是第一款并发的垃圾回收器,相比Serial来说垃圾回收不需要阻塞所有线程,第一次实现了让垃圾回收线程和用户线程同时工作。

  3. Serial Old是Serial的老年代版本。

  4. Parallel Scavenge同样是作用在新生代且是多线程,不过它的设计目标是达到一个可控制的吞吐量

  5. Parallel Old是Parallel Scavenge收集器的老年代版本,我们可以把它和Parallel Scavenge搭配一起使用。

  6. CMS是一种以最短停顿时间为目标的多线程收集器,下文我会介绍CMS实现最短停顿的原理。

  7. G1收集器可以说是CMS的升级版

小伙伴可以根据业务实际情况来为各个年代搭配不同的垃圾回收器,以下的垃圾回收器如果有线连接,说明它们之间可以搭配使用。

在这里插入图片描述

2.4 CMS原理

面试官:CMS为什么有较短的停顿?

CMS采用了标记-清除算法,整个运作过程分为了初始标记、并发标记、重新标记、并发清除四个阶段。

其中初始标记、重新标记的停顿时间是比较短的,而耗时最长的并发标记、并发清除能够和用户线程一起并发工作不需要停顿,可以说CMS只需要造成初始标记、重新标记带来的短时间停顿。

2.5 CMS的缺点

面试官:那它有什么缺点?

  1. CMS是多线程的,在垃圾回收时会占用一部分线程,可能会使系统变得相对较慢。
  2. CMS并发清理时用户线程还在运行着,也就是说还会有新的垃圾不断产生,这些垃圾被称为浮动垃圾。因为浮动垃圾产生在标记阶段后,很明显CMS本次收集是无法处理这些浮动垃圾的,只能等到下一次GC回收。
  3. CMS采用标记-清除算法,标记-清除算法的缺点是会产生空间碎片,有可能造成大对象找不到足够的连续空间而发生OOM的情况。

2.6 G1垃圾回收器

面试官:你说G1是CMS的升级版,为什么?

G1垃圾回收器设计之初被赋予的使命是未来可以替换掉JDK1.5中发布的CMS垃圾回收器。所以大家可想而知,CMS垃圾回收器的优点G1垃圾回收器都有,另外G1垃圾回收器也避免了CMS的一些不足。

  1. G1采用的垃圾回收算法是标记-整理算法,避免了CMS采用标记-清除可能产生的空间碎片。
  2. 其他收集器在新生代、老年代分别采用不同收集器进行配合,而G1垃圾回收器可以不需要其他收集器配合就能独立管理整个GC。

3. 垃圾回收算法

面试官:垃圾回收算法都有什么?

垃圾回收算法一共有四种,其中最基础的垃圾回收算法是标记-清除算法,其他算法其实都是对标记-清除算法的优化而产生的,我们继续往下看。

(1)标记-清除算法。

标记-清除算法顾名思义分为标记清除两个阶段,首先标记出所有可回收的对象,标记完成后统一进行清除。但该算法有一个缺点,被标记和未标记的对象都是分散存储在内存中的,当清除标记对象后会出现空间碎片的情况,如下图:

在这里插入图片描述

(2)复制算法。

复制算法把内存划分为容量相等的两块,每次只使用一块,当这一块内存不足时就将存活的对象复制到另一块中,同时清除当前块的内存空间。这种算法实现简单且运行高效,也不会产生空间碎片的情况,因为新生代的GC是比较频繁的,所以复制算法也广泛用于新生代的垃圾回收。但缺点很明显是浪费了50%的内存空间

(3)标记-整理算法。

标记-整理算法是对标记-清除算法的优化。该算法在内存到达一定量后,会把所有已标记的垃圾对象都向一端里移动,然后以存活对象所在的一端为边界,清除边界内所有内存,避免了标记-清除算法可能产生的空间碎片。

(4)分代收集算法。

一般实际业务系统都是采用分代收集算法。分代顾名思义把JVM内存拆分,分为了新生代、老年代,对不同年代的垃圾回收采用不同的垃圾回收算法来确保回收效率。

大家可以看下自己公司的JDK使用了什么垃圾回收器,加深下对本篇的理解。

# 打印JVM启动时的命令行标志
java -XX:+PrintCommandLineFlags -version

3.1 优化复制算法

面试官:复制算法可以怎么优化?

复制算法把内存划分为容量相等的两块,也就是按1:1分配内存,但这也浪费了50%空间

可以把内存分为一块较大的Eden空间和两块较小的Survivor空间,每次只使用Eden空间和其中一块Survivor空间,而另一块Survivor空间用来保存回收时还存活的对象。这样就只浪费了其中一块Survivor空间的内存。

覆盖Java程序员所需掌握的Java核心知识、面试重点,本博客收录在我开源的《Java学习面试指南》中,会一直完善下去,希望收到大家的 ⭐ Star ⭐支持,这是我创作的最大动力: https://github.com/hdgaadd/JavaGetOffer

未完待续。。。

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

相关文章
|
4月前
|
存储 算法 Oracle
极致八股文之JVM垃圾回收器G1&ZGC详解
本文作者分享了一些垃圾回收器的执行过程,希望给大家参考。
|
29天前
|
监控 算法 Java
Java虚拟机(JVM)的垃圾回收机制深度解析####
本文深入探讨了Java虚拟机(JVM)的垃圾回收机制,旨在揭示其背后的工作原理与优化策略。我们将从垃圾回收的基本概念入手,逐步剖析标记-清除、复制算法、标记-整理等主流垃圾回收算法的原理与实现细节。通过对比不同算法的优缺点及适用场景,为开发者提供优化Java应用性能与内存管理的实践指南。 ####
|
21天前
|
监控 算法 Java
Java虚拟机(JVM)垃圾回收机制深度剖析与优化策略####
本文作为一篇技术性文章,深入探讨了Java虚拟机(JVM)中垃圾回收的工作原理,详细分析了标记-清除、复制算法、标记-压缩及分代收集等主流垃圾回收算法的特点和适用场景。通过实际案例,展示了不同GC(Garbage Collector)算法在应用中的表现差异,并针对大型应用提出了一系列优化策略,包括选择合适的GC算法、调整堆内存大小、并行与并发GC调优等,旨在帮助开发者更好地理解和优化Java应用的性能。 ####
26 0
|
20天前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
24天前
|
机器学习/深度学习 监控 算法
Java虚拟机(JVM)的垃圾回收机制深度剖析####
本文深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法、性能调优策略及未来趋势。通过实例解析,为开发者提供优化Java应用性能的思路与方法。 ####
34 1
|
27天前
|
监控 算法 Java
Java虚拟机垃圾回收机制深度剖析与优化策略####
【10月更文挑战第21天】 本文旨在深入探讨Java虚拟机(JVM)中的垃圾回收机制,揭示其工作原理、常见算法及参数调优技巧。通过案例分析,展示如何根据应用特性调整GC策略,以提升Java应用的性能和稳定性,为开发者提供实战中的优化指南。 ####
41 5
|
29天前
|
存储 算法 安全
JVM常见面试题(四):垃圾回收
堆区域划分,对象什么时候可以被垃圾器回收,如何定位垃圾——引用计数法、可达性分析算法,JVM垃圾回收算法——标记清除算法、标记整理算法、复制算法、分代回收算法;JVM垃圾回收器——串行、并行、CMS垃圾回收器、G1垃圾回收器;强引用、软引用、弱引用、虚引用
|
27天前
|
存储 算法 Java
JVM进阶调优系列(10)敢向stop the world喊卡的G1垃圾回收器 | 有必要讲透
本文详细介绍了G1垃圾回收器的背景、核心原理及其回收过程。G1,即Garbage First,旨在通过将堆内存划分为多个Region来实现低延时的垃圾回收,每个Region可以根据其垃圾回收的价值被优先回收。文章还探讨了G1的Young GC、Mixed GC以及Full GC的具体流程,并列出了G1回收器的核心参数配置,帮助读者更好地理解和优化G1的使用。
|
28天前
|
监控 Java 测试技术
Elasticsearch集群JVM调优垃圾回收器的选择
Elasticsearch集群JVM调优垃圾回收器的选择
48 1
|
2月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
81 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS