JVM 垃圾回收的几种类型

我们经常会听到许多垃圾回收的术语,例如:Minor GC、Major GC、Young GC、Old GC、Full GC、Stop-The-World 等。但这些 GC 术语到底指的是什么,它们之间的区别到底是什么?今天我们就来详细说说。

 

 

到底谁是垃圾?

要进行垃圾回收,最为重要的一个问题是:判断谁是垃圾?

联想其日常生活中,如果一个东西经常没被使用,那么这个对象可以说就是垃圾。在 Java 中也是如此,如果一个对象不可能再被引用,那么这个对象就是垃圾,应该被回收。

根据这个思想,我们很容易想到使用引用计数的方法来判断垃圾。在一个对象被引用时加一,被去除引用时减一,这样我们就可以通过判断引用计数是否为零来判断一个对象是否为垃圾。这种方法我们一般称之为「引用计数法」。

上面的这种方法虽然简单,但是其存在一个致命的问题,那就是循环引用。

A 引用了 B,B 引用了 C,C 引用了 A,它们各自的引用计数都为 1。但是它们三个对象却从未被其他对象引用,只有它们自身互相引用。从垃圾的判断思想来看,它们三个确实是不被其他对象引用的,但是此时它们的引用计数却不为零。这就是引用计数法存在的循环引用问题。

而现今的 Java 虚拟机判断垃圾对象使用的是:GC Root Tracing 算法。其大概的过程是这样:从 GC Root 出发,所有可达的对象都是存活的对象,而所有不可达的对象都是垃圾。

可以看到这里最重要的就是 GC Root 这个集合了,其实 GC Root 就是一组活跃引用的集合。但是这个集合又与一般的对象集合不太一样,这些集合是经过特意筛选出来的,通常包括:

  • 所有当前被加载的 Java 类
  • Java 类的引用类型静态变量
  • Java类的运行时常量池里的引用类型常量
  • VM的一些静态数据结构里指向GC堆里的对象的引用
  • 等等

简单地说,GC Root 就是经过精心挑选的一组活跃引用,这些引用是肯定存活的。那么通过这些引用延伸到的对象,自然也是存活的。

 

 

Minor GC

从年轻代空间回收内存被称为 Minor GC,有时候也称之为 Young GC。对于 Minor GC,你需要知道的一些点:

  • 当 JVM 无法为一个新的对象分配空间时会触发 Minor GC,比如当 Eden 区满了。所以 Eden 区越小,越频繁执行 Minor GC。
  • 当年轻代中的 Eden 区分配满的时候,年轻代中的部分对象会晋升到老年代,所以 Minor GC 后老年代的占用量通常会有所升高。
  • 质疑常规的认知,所有的 Minor GC 都会触发 Stop-The-World,停止应用程序的线程。对于大部分应用程序,停顿导致的延迟都是可以忽略不计的,因为大部分 Eden 区中的对象都能被认为是垃圾,永远也不会被复制到 Survivor 区或者老年代空间。如果情况相反,即 Eden 区大部分新生对象不符合 GC 条件(即他们不被垃圾回收器收集),那么 Minor GC 执行时暂停的时间将会长很多(因为他们要JVM要将他们复制到 Survivor 区或老年代)。

 

 

Major GC

从老年代空间回收内存被称为 Major GC,有时候也称之为 Old GC。

许多 Major GC 是由 Minor GC 触发的,所以很多情况下将这两种 GC 分离是不太可能的。当进行 Minor GC 时,如果年轻代空间不够,那么就会触发 Major GC 将存活较久的对象移动到老年代中,从而腾出更多的年轻代空间。

 

 

Full GC

Full GC 是清理整个堆空间 —— 包括年轻代、老年代和永久代(如果有的话)。因此 Full GC 可以说是 Minor GC 和 Major GC 的结合。

当准备要触发一次 Minor GC 时,如果发现年轻代的剩余空间比以往晋升的空间小,则不会触发 Minor GC 而是转为触发 Full GC。因为JVM此时认为:之前这么大空间的时候已经发生对象晋升了,那现在剩余空间更小了,那么很大概率上也会发生对象晋升。既然如此,那么我就直接帮你把事情给做了吧,直接来一次 Full GC,整理一下老年代和年轻代的空间。

另外,即在永久代分配空间但已经没有足够空间时,也会触发 Full GC。

 

 

Stop-The-World

Stop-The-World,中文一般翻译为全世界暂停,是指在进行垃圾回收时因为标记或清理的需要,必须让所有执行任务的线程停止执行任务,从而让垃圾回收线程回收垃圾的时间间隔。

在 Stop-The-World 这段时间里,所有非垃圾回收线程都无法工作,都暂停下来。只有等到垃圾回收线程工作完成才可以继续工作。可以看出,Stop-The-World 时间的长短将关系到应用程序的响应时间,因此在 GC 过程中,Stop-The-World 的时间是一个非常重要的指标。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVM(Java虚拟机)垃圾回收器是负责管理内存的重要组件。它负责清理不再使用的对象,以便为新对象腾出空间。在Java中,常见的垃圾回收器有以下几种: 1. Serial(串行)垃圾回收器:它是最早实现的垃圾回收器,使用单线程进行垃圾回收。它会暂停应用程序的所有线程,并逐个扫描内存中的对象进行回收。虽然效率较低,但对于小型应用程序或单核处理器的系统来说是一个不错的选择。 2. Parallel(并行)垃圾回收器:与串行垃圾回收器类似,但它使用多个线程并行进行垃圾回收。这样可以提高回收效率,但需要更多的系统资源。它适用于多CPU系统,可以加快垃圾回收的速度。 3. CMS(Concurrent Mark and Sweep,并发标记清除)垃圾回收器:它是一种并发回收器,允许应用程序在垃圾回收过程中继续运行。它使用多个线程来标记和清除内存中的垃圾对象。此外,CMS使用了一种增量算法,避免了长时间的停顿时间,对于对停顿时间敏感的应用程序来说是一种选择。 4. G1(Garbage First)垃圾回收器:它是JDK 7中引入的一种新型垃圾回收器。G1使用分区的方式管理堆内存,将整个堆分成多个小块。通过基于目标停顿时间的方式,它可以根据应用程序的需求来选择性地回收不再使用的对象,以减少停顿时间和提高吞吐量。 不同的垃圾回收器适用于不同的应用场景,开发人员可以根据应用程序的需求和系统配置来选择合适的垃圾回收器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值