当前位置 : 主页 > 编程语言 > java >

Java垃圾回收全过程

来源:互联网 收集:自由互联 发布时间:2023-09-06
JVM中一次完整的垃圾回收(GC)过程。这里以HotSpot虚拟机为例,并将参考其中的一种常用的垃圾回收器:G1(Garbage-First)。 堆的划分 在HotSpot JVM中,堆(Heap)通常被划分为以下几个部

JVM中一次完整的垃圾回收(GC)过程。这里以HotSpot虚拟机为例,并将参考其中的一种常用的垃圾回收器:G1(Garbage-First)。

堆的划分

在HotSpot JVM中,堆(Heap)通常被划分为以下几个部分:

  • 年轻代(Young Generation): 这部分进一步分为Eden区和两个Survivor区(S0和S1)。
  • 老年代(Old Generation): 存放长时间存活的对象。
  • 元空间(Metaspace): 存放类的元数据。

阶段1:Minor GC

1.1 初始标记(Initial Mark)

  • 停止所有的应用线程(Stop-The-World, STW)。
  • 标记从GC Roots直接可达的对象。

1.2 并发标记(Concurrent Mark)

  • 在应用线程运行的同时,标记通过已标记对象间接可达的对象。

1.3 最终标记(Final Mark)

  • 处理在并发标记阶段发生变化(如新创建的对象)的标记。

1.4 清除与复制(Evacuation)

  • 删除未标记的对象,并将存活的对象复制到Survivor区或Old区。

在HotSpot JVM中,当对象在年轻代(Young Generation)的Survivor区经过一定次数的Minor GC后仍然存活,它们会被晋升(promoted)到老年代(Old Generation)。这个晋升过程也被称为“老年代担保”(Tenuring Threshold)。这里有几个关键点需要注意:

晋升阈值(Tenuring Threshold)

JVM有一个称为“晋升阈值”(Tenuring Threshold)的设置,该设置定义了一个对象在被晋升到老年代之前必须经历多少次Minor GC。这个阈值可以通过JVM参数 -XX:MaxTenuringThreshold-XX:InitialTenuringThreshold 来设置。

担保机制

当Minor GC发生时,JVM需要确保所有存活的对象都有足够的空间。如果Survivor区没有足够的空间来容纳这些对象,JVM有两种选择:

  1. 尝试在老年代中找到空间: 如果老年代有足够的空间来容纳这些对象,则这些对象会被直接晋升到老年代,即使它们的年龄没有达到晋升阈值。
  2. 触发Full GC: 如果老年代没有足够的空间来容纳这些对象,JVM可能会选择触发一次Full GC来清理整个堆(包括老年代)。

动态调整

在运行时,JVM可能会动态地调整晋升阈值。这是基于之前GC活动的统计数据来进行的,目的是优化内存使用和减少Full GC的次数。

为什么需要担保机制?

担保机制的目的是为了确保堆内存的有效利用和GC性能的优化。通过将经常存活的对象移动到老年代,Minor GC可以更高效地回收年轻代,因为老年代的GC通常较少发生。

阶段2:Full GC(Major GC)

Full GC通常会清理整个堆空间,包括年轻代和老年代。

2.1 初始标记(Initial Mark)

  • STW事件。
  • 标记所有从GC Roots直接可达的对象。

2.2 根区域扫描(Root Region Scanning)

  • 标记所有从"根区域"(如老年代)可达的对象。

2.3 并发标记(Concurrent Mark)

  • 与应用线程并行,标记所有存活的对象。

2.4 最终标记(Final Mark)

  • STW事件。
  • 处理在并发标记期间发生变化的标记。

2.5 筛选回收(Cleanup)

  • 清除不再使用的内存区域,并为即将发生的分配做准备。

额外阶段:元空间回收(Metaspace Collection)

  • 如果元空间满了,会触发Full GC来清理类的元数据。

监控和调试

  • JVM提供了许多标志和工具来监控和调试GC行为,如-XX:+PrintGCDetails和JVisualVM等。
上一篇:Nacos的使用
下一篇:没有了
网友评论