Java中的垃圾处理

什么是垃圾收集,为什么需要它,它是如何工作的?

垃圾回收是通过销毁未使用的对象来回收全部运行时内存的过程。每个应用程序都需要内存才能运行。但是,计算机内存是有限的。因此,清除未使用的旧数据以为新数据腾出空间很重要。

垃圾回收的主要目的是通过销毁不包含引用的对象来释放堆内存。当一个对象没有被引用时,它被认为是死的并且不再需要了。这样就可以回收对象占用的内存。

Java内存结构

本机内存– 所有可用的系统内存。

– 分配给堆的本机内存部分。这是 JVM 存储对象的地方。这是所有应用程序线程的公共空间。此内存区域的大小可使用 -Xms(最小大小)和 -Xmx(最大大小)选项进行配置。

——用来存放局部变量和方法调用栈。每个线程都有它的堆栈。

元空间– 此内存存储类元数据和静态变量。这个空间也是大家共享的。由于元空间是本机内存的一部分,它的大小取决于平台。可以使用 MaxMetaspaceSize 标志配置用于元空间的内存量的上限。

PermGen (Permanent Generation) – 在 Java 7 之前一直存在。从 Java 8 开始,它被 Metaspace 区域所取代。

CodeCache – JIT 编译器编译频繁执行的代码,将其转换为本地机器代码,并缓存它以加快执行速度。这也是本机内存的一部分。

垃圾收集

Java 中的垃圾收集是一个自动过程。程序员不需要选择对象并删除它们。

垃圾收集使用 Mark & Sweep 算法。该算法包括三个阶段:

  1. Mark标记。第一步,GC 扫描所有对象并标记活动对象(仍在使用的对象)。在这个阶段,程序执行被暂停。此步骤也称为“停止世界”。
  2. Sweep扫一扫。在这一步,内存被步骤中没有看到的对象占用。
  3. Compact紧凑。在清理过程中幸存下来的对象被移动到单个连续的内存块中。这减少了堆碎片并使得分配新对象变得更容易和更快。

对象生成

什么是对象生成?

Java 中的垃圾收集器实现了按年龄对对象进行分类的分代垃圾收集策略。

为了优化垃圾收集,堆内存进一步分为四个区域。对象根据它们的年龄(它们在应用程序中使用了多长时间)放置在这些区域中。

  1. 新生成Young Generation。这是创建新对象的地方。年轻代区域分为三个部分:Eden、S0、S1(Survivor Space)。
  2. 老一代Old Generation。这里有长寿的物体。

什么是停止世界?

当标记阶段开始时,应用程序停止运行。标记完成后,应用程序恢复其工作。任何垃圾收集都是“停止世界”。

什么是世代假设?

如前所述,生成用于优化标记和扫描阶段。世代假设说:

  1. 大多数物体不会持续很长时间。
  2. 如果该物体幸存下来,那么它很可能会永远存在。
  3. 标记和清扫步骤花费的时间更少,有很多碎屑。也就是说,如果您分析小而多的死对象,标记会更快。

因此,基于生成的垃圾收集算法如下所示:

  1. 新对象在 Eden 区域中创建。幸存者区域(S0、S1)目前是空的。
  2. 当 Eden 区域填满时,会发生 Minor GC。Minor GC是对年轻代进行标记和清除操作的过程。
  3. 在 Minor GC 之后,活动对象被移动到 Survivor 的某个区域(例如,S0)。死物被完全移除。
  4. 随着应用程序的运行,伊甸园空间充满了新的对象。在下一次 Minor GC 时,年轻代和 S0 区域被清除。这次幸存的对象被移动到区域 S1 并且它们的年龄增加(标记它们在垃圾收集中幸存下来)。
  5. 在下一次 Minor GC 时,重复该过程。然而,这一次,幸存者的区域被颠倒了。活体移动到 S0 并且它们的年龄增加。伊甸园和 S1 区域被清除。
  6. Survivor 区域之间的对象被复制一定次数(直到它们在一定数量的 Minor GC 中存活)或只要有足够的空间。然后将这些对象复制到旧区域。
  7. GC少校。使用 Major GC,对老年代执行标记和清除步骤。Major GC 比 Minor GC 慢,因为老年代主要是活动对象。

使用世代的好处

Minor GC 发生在堆的较小部分(约 2/3 的堆)。标记步骤是有效的,因为该区域很小并且主要由死对象组成。

使用世代的缺点

在任何给定时间,Survivor 空间之一(S0 或 S1)都是空的且未使用。

垃圾收集器类型

串行

使用一个线程。

优点

有效,因为线程之间的交互没有开销。

何时使用

单处理器机器。使用小型数据集。

要启用的标志

-XX:+UseSerialGC

平行

使用多个线程。

优点

多线程加速垃圾收集。

何时使用

最佳性能是首要任务。一秒或更长时间的 GC 暂停是可以接受的。使用中型和大型数据集。适用于在多处理器或多线程硬件上运行的应用程序。

要启用的标志

-XX:+UseParallelGC

内容管理系统

被称为低暂停比例收集器。

优点

最大限度地减少停机时间,这是许多应用程序的大部分内容。但是要完成这项任务,您必须牺牲 CPU 负载,并且通常会牺牲整体吞吐量任务。

何时使用

收集器可能适用于使用大量长寿命数据的应用程序。

要启用的标志

-XX:+UseConcMarkSweepGC

G1(垃圾优先)

并行工作者应用程序的艰苦工作正在进行中。

优点

它既可以用于小型系统,也可以用于具有大量处理器和大量内存的大型系统。

何时使用

当带宽跳过响应时间时,GC Pauses 必须小于一秒。

要启用的标志

-XX:+UseConcMarkSweepGC

垃圾优先

并行应用程序的所有艰苦工作都已完成。

优点

低延迟。

何时使用

响应时间优先。

要启用的标志

-XX:+UseG1GC