Loading

Java中的G1GC是如何工作的.18219565

原文:How G1 Garbage Collector work in Java
作者:Perspective Mentor

G1垃圾收集器采用了一个全新的垃圾收集方式,这让它在Java中的其它GC算法中鹤立鸡群。

介绍

G1(Garbage-First)是作为ParallelCMS的替代者被引入到Java中的。它的设计目标是提供更加可预测的程序暂停时间,同时仍然提供优秀的总体吞吐量。下面是一个G1GC如何工作的概述。

堆分区
堆被分为多个区域,每一个区域都是一个连续的内存块,这些区域通常具有不同的大小,并且它们服务于不同的目的。在G1中有三种主要的区域类型:

  • Eden:新建的对象被分配到的区域
  • Survivor:通常有两个Survivor区域(S0和S1),它们用于保存活了一个或多个GC周期的对象
  • Old Generation:这个区域用于保存长生命周期的对象,它们存活了很多次GC周期

堆中不同大小的多个区域

每一个块大小为1MB到32MB
总块数大概是2048个(或者基于JVM的内存大小可能更小)。
但是块的总数不能超过2048个。

举个例子,如果我们给JVM分配了8GB内存,它将会创建大约20003-4MB的块,每一个块可能是Eden、Servivor或者Old Generation类型,而且仍有一些尚未分配的空间。

Eden、Survivor和Old Generation的块数量可能不同,New Generation(Eden + Survivor)可能具有最小5%最大60%的JVM内存,这根据不同类型的应用来决定,因此在G1GC中不推荐固定的新生代大小。

如果我们需要创建一个大于块大小的对象会发生什么?我们会在最后处理。

初始标记

G1从一个初始标记阶段开始,在这个阶段,它识别并标记Old Generation的存活对象,这个阶段与用户线程并发,所以它对应用性能只有很小的冲击。

并发Mark

在初始标记后,G1执行一个并发标记去识别整个堆中所有区域中更多的存活对象,这个阶段与用户线程并发,允许程序继续执行。

重标记

一旦并发标记完成,G1执行一个重标记去识别自初始标记起已经发生改变的对象(引用关系发生改变),这是为了确保精确的识别存活对象,这个阶段将导致一个应用程序执行的短暂暂停。

并发清理

在重标记阶段后,G1执行并发清理,这涉及到从不再使用的内存区域回收内存。与用户线程并发完成。

Evacuation

G1使用一个被称为Evacuation的过程来将存活对象从一个区域移动到另一个区域。它选择具有最多垃圾的区域,对它们进行优先级排序以进行Evacuation。目标是清空具有大量垃圾的区域以最小化碎片,提升堆的总体利用率。

混合GC

G1使用被称作“混合GC”的概念来执行垃圾收集,它即会在Young Generation(Eden以及Survivor)收集,也会在Old Generation收集。这允许G1获得更好的总体堆利用率并且避免FullGC带来的长暂停时间。

译者:受不了了,后面统一用老年代代表Old Generation,用年轻代代表Young Generation

回收集

G1维护一个被称作“回收集”的区域列表,其中包含了垃圾回收的候选区域。这些区域基于它们的垃圾内容被选择,并且会在GC周期(GC Cycle)中被回收。

暂停时间目标

G1致力于达到一个用户定义的暂停时间目标。它通过控制回收集的大小以及其它参数来动态调整它的行为以达到这个目标。

重复周期

G1持续性的重复GC周期,根据堆状态以及期待的暂停时间目标调整其优先级。

实现

我们将编写一个小程序,并使用G1GC算法来运行它。我们创建一个类A,在A中我们创建大小为100的Double列表,在主类G1GCVerification中,我们以1秒的睡眠时间重复创建对象A。

import java.util.ArrayList;
import java.util.List;

public class G1GCVerification {

    public static void main(String[] args) {
        createRecurringObjects();
    }

    private static void createRecurringObjects() {
        for (int i=0 ; i< 10000; i++) {
            for(int j=0; j<100000; j++){
                A a = new A();
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

class A {
    List<Double> list = new ArrayList<>(100);
}

jcmd命令

这个命令在java9之后可用。如下就是jcmd命令的输出(注意:为了捕获jcmd的输出,程序在Intellij IDE中执行,并且具有很少量的内存)

>java -version
openjdk version "17.0.5" 2022-10-18 LTS
OpenJDK Runtime Environment Corretto-17.0.5.8.1 (build 17.0.5+8-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.5.8.1 (build 17.0.5+8-LTS, mixed mode, sharing)

>jps
13296 Jps
6912 GradleDaemon
8432
12572 G1GCVerification
7884 GradleDaemon

> jcmd 12572 VM.info

jcmd命令打印了大量输出,我们将讨论其中的一些重要部分。

****Heap:
 garbage-first heap   total 260096K, used 34351K [0x0000000702400000, 0x0000000800000000)
  region size 2048K, 18 young (36864K), 1 survivors (2048K)
 Metaspace       used 141K, committed 384K, reserved 1056768K
  class space    used 4K, committed 128K, reserved 1048576K

Heap Regions: E=young(eden), S=young(survivor), O=old, HS=humongous(starts), HC=humongous(continues), CS=collection set, F=free, OA=open archive, CA=closed archive, TAMS=top-at-mark-start (previous, next)
|   0|0x0000000702400000, 0x000000070248ac00, 0x0000000702600000| 27%| O|  |TAMS 0x0000000702400000, 0x0000000702400000| Untracked
|   1|0x0000000702600000, 0x0000000702600000, 0x0000000702800000|  0%| F|  |TAMS 0x0000000702600000, 0x0000000702600000| Untracked
|   2|0x0000000702800000, 0x0000000702800000, 0x0000000702a00000|  0%| F|  |TAMS 0x0000000702800000, 0x0000000702800000| Untracked
|   3|0x0000000702a00000, 0x0000000702a00000, 0x0000000702c00000|  0%| F|  |TAMS 0x0000000702a00000, 0x0000000702a00000| Untracked
|   4|0x0000000702c00000, 0x0000000702c00000, 0x0000000702e00000|  0%| F|  |TAMS 0x0000000702c00000, 0x0000000702c00000| Untracked
|   5|0x0000000702e00000, 0x0000000702e00000, 0x0000000703000000|  0%| F|  |TAMS 0x0000000702e00000, 0x0000000702e00000| Untracked
|   6|0x0000000703000000, 0x0000000703000000, 0x0000000703200000|  0%| F|  |TAMS 0x0000000703000000, 0x0000000703000000| Untracked
|   7|0x0000000703200000, 0x0000000703200000, 0x0000000703400000|  0%| F|  |TAMS 0x0000000703200000, 0x0000000703200000| Untracked
|   8|0x0000000703400000, 0x0000000703400000, 0x0000000703600000|  0%| F|  |TAMS 0x0000000703400000, 0x0000000703400000| Untracked
|   9|0x0000000703600000, 0x0000000703600000, 0x0000000703800000|  0%| F|  |TAMS 0x0000000703600000, 0x0000000703600000| Untracked
|  10|0x0000000703800000, 0x0000000703800000, 0x0000000703a00000|  0%| F|  |TAMS 0x0000000703800000, 0x0000000703800000| Untracked
|  11|0x0000000703a00000, 0x0000000703a00000, 0x0000000703c00000|  0%| F|  |TAMS 0x0000000703a00000, 0x0000000703a00000| Untracked
|  12|0x0000000703c00000, 0x0000000703c00000, 0x0000000703e00000|  0%| F|  |TAMS 0x0000000703c00000, 0x0000000703c00000| Untracked
|  13|0x0000000703e00000, 0x0000000703e00000, 0x0000000704000000|  0%| F|  |TAMS 0x0000000703e00000, 0x0000000703e00000| Untracked
|  14|0x0000000704000000, 0x0000000704000000, 0x0000000704200000|  0%| F|  |TAMS 0x0000000704000000, 0x0000000704000000| Untracked
|  15|0x0000000704200000, 0x0000000704200000, 0x0000000704400000|  0%| F|  |TAMS 0x0000000704200000, 0x0000000704200000| Untracked
|  16|0x0000000704400000, 0x0000000704400000, 0x0000000704600000|  0%| F|  |TAMS 0x0000000704400000, 0x0000000704400000| Untracked
|  17|0x0000000704600000, 0x0000000704600000, 0x0000000704800000|  0%| F|  |TAMS 0x0000000704600000, 0x0000000704600000| Untracked
|  18|0x0000000704800000, 0x0000000704800000, 0x0000000704a00000|  0%| F|  |TAMS 0x0000000704800000, 0x0000000704800000| Untracked
|  19|0x0000000704a00000, 0x0000000704a00000, 0x0000000704c00000|  0%| F|  |TAMS 0x0000000704a00000, 0x0000000704a00000| Untracked
|  20|0x0000000704c00000, 0x0000000704c00000, 0x0000000704e00000|  0%| F|  |TAMS 0x0000000704c00000, 0x0000000704c00000| Untracked
|  21|0x0000000704e00000, 0x0000000704e00000, 0x0000000705000000|  0%| F|  |TAMS 0x0000000704e00000, 0x0000000704e00000| Untracked
|  22|0x0000000705000000, 0x0000000705000000, 0x0000000705200000|  0%| F|  |TAMS 0x0000000705000000, 0x0000000705000000| Untracked
|  23|0x0000000705200000, 0x0000000705200000, 0x0000000705400000|  0%| F|  |TAMS 0x0000000705200000, 0x0000000705200000| Untracked
|  24|0x0000000705400000, 0x0000000705400000, 0x0000000705600000|  0%| F|  |TAMS 0x0000000705400000, 0x0000000705400000| Untracked
|  25|0x0000000705600000, 0x0000000705600000, 0x0000000705800000|  0%| F|  |TAMS 0x0000000705600000, 0x0000000705600000| Untracked
|  26|0x0000000705800000, 0x0000000705800000, 0x0000000705a00000|  0%| F|  |TAMS 0x0000000705800000, 0x0000000705800000| Untracked
|  27|0x0000000705a00000, 0x0000000705a00000, 0x0000000705c00000|  0%| F|  |TAMS 0x0000000705a00000, 0x0000000705a00000| Untracked
|  28|0x0000000705c00000, 0x0000000705c00000, 0x0000000705e00000|  0%| F|  |TAMS 0x0000000705c00000, 0x0000000705c00000| Untracked
|  29|0x0000000705e00000, 0x0000000705e00000, 0x0000000706000000|  0%| F|  |TAMS 0x0000000705e00000, 0x0000000705e00000| Untracked
|  30|0x0000000706000000, 0x0000000706000000, 0x0000000706200000|  0%| F|  |TAMS 0x0000000706000000, 0x0000000706000000| Untracked
|  31|0x0000000706200000, 0x0000000706200000, 0x0000000706400000|  0%| F|  |TAMS 0x0000000706200000, 0x0000000706200000| Untracked
|  32|0x0000000706400000, 0x0000000706400000, 0x0000000706600000|  0%| F|  |TAMS 0x0000000706400000, 0x0000000706400000| Untracked
|  33|0x0000000706600000, 0x0000000706600000, 0x0000000706800000|  0%| F|  |TAMS 0x0000000706600000, 0x0000000706600000| Untracked
|  34|0x0000000706800000, 0x0000000706800000, 0x0000000706a00000|  0%| F|  |TAMS 0x0000000706800000, 0x0000000706800000| Untracked
|  35|0x0000000706a00000, 0x0000000706a00000, 0x0000000706c00000|  0%| F|  |TAMS 0x0000000706a00000, 0x0000000706a00000| Untracked
|  36|0x0000000706c00000, 0x0000000706c00000, 0x0000000706e00000|  0%| F|  |TAMS 0x0000000706c00000, 0x0000000706c00000| Untracked
|  37|0x0000000706e00000, 0x0000000706e00000, 0x0000000707000000|  0%| F|  |TAMS 0x0000000706e00000, 0x0000000706e00000| Untracked
|  38|0x0000000707000000, 0x0000000707000000, 0x0000000707200000|  0%| F|  |TAMS 0x0000000707000000, 0x0000000707000000| Untracked
|  39|0x0000000707200000, 0x0000000707200000, 0x0000000707400000|  0%| F|  |TAMS 0x0000000707200000, 0x0000000707200000| Untracked
|  40|0x0000000707400000, 0x0000000707400000, 0x0000000707600000|  0%| F|  |TAMS 0x0000000707400000, 0x0000000707400000| Untracked
|  41|0x0000000707600000, 0x0000000707600000, 0x0000000707800000|  0%| F|  |TAMS 0x0000000707600000, 0x0000000707600000| Untracked
|  42|0x0000000707800000, 0x0000000707800000, 0x0000000707a00000|  0%| F|  |TAMS 0x0000000707800000, 0x0000000707800000| Untracked
|  43|0x0000000707a00000, 0x0000000707a00000, 0x0000000707c00000|  0%| F|  |TAMS 0x0000000707a00000, 0x0000000707a00000| Untracked
|  44|0x0000000707c00000, 0x0000000707c00000, 0x0000000707e00000|  0%| F|  |TAMS 0x0000000707c00000, 0x0000000707c00000| Untracked
|  45|0x0000000707e00000, 0x0000000707e00000, 0x0000000708000000|  0%| F|  |TAMS 0x0000000707e00000, 0x0000000707e00000| Untracked
|  46|0x0000000708000000, 0x0000000708000000, 0x0000000708200000|  0%| F|  |TAMS 0x0000000708000000, 0x0000000708000000| Untracked
|  47|0x0000000708200000, 0x0000000708200000, 0x0000000708400000|  0%| F|  |TAMS 0x0000000708200000, 0x0000000708200000| Untracked
|  48|0x0000000708400000, 0x0000000708400000, 0x0000000708600000|  0%| F|  |TAMS 0x0000000708400000, 0x0000000708400000| Untracked
|  49|0x0000000708600000, 0x0000000708600000, 0x0000000708800000|  0%| F|  |TAMS 0x0000000708600000, 0x0000000708600000| Untracked
|  50|0x0000000708800000, 0x0000000708800000, 0x0000000708a00000|  0%| F|  |TAMS 0x0000000708800000, 0x0000000708800000| Untracked
|  51|0x0000000708a00000, 0x0000000708a00810, 0x0000000708c00000|  0%| S|CS|TAMS 0x0000000708a00000, 0x0000000708a00000| Complete
|  52|0x0000000708c00000, 0x0000000708c00000, 0x0000000708e00000|  0%| F|  |TAMS 0x0000000708c00000, 0x0000000708c00000| Untracked
|  53|0x0000000708e00000, 0x0000000708e00000, 0x0000000709000000|  0%| F|  |TAMS 0x0000000708e00000, 0x0000000708e00000| Untracked
|  54|0x0000000709000000, 0x0000000709000000, 0x0000000709200000|  0%| F|  |TAMS 0x0000000709000000, 0x0000000709000000| Untracked
|  55|0x0000000709200000, 0x0000000709200000, 0x0000000709400000|  0%| F|  |TAMS 0x0000000709200000, 0x0000000709200000| Untracked
|  56|0x0000000709400000, 0x0000000709400000, 0x0000000709600000|  0%| F|  |TAMS 0x0000000709400000, 0x0000000709400000| Untracked
|  57|0x0000000709600000, 0x0000000709600000, 0x0000000709800000|  0%| F|  |TAMS 0x0000000709600000, 0x0000000709600000| Untracked
|  58|0x0000000709800000, 0x0000000709800000, 0x0000000709a00000|  0%| F|  |TAMS 0x0000000709800000, 0x0000000709800000| Untracked
|  59|0x0000000709a00000, 0x0000000709a00000, 0x0000000709c00000|  0%| F|  |TAMS 0x0000000709a00000, 0x0000000709a00000| Untracked
|  60|0x0000000709c00000, 0x0000000709c00000, 0x0000000709e00000|  0%| F|  |TAMS 0x0000000709c00000, 0x0000000709c00000| Untracked
|  61|0x0000000709e00000, 0x0000000709e00000, 0x000000070a000000|  0%| F|  |TAMS 0x0000000709e00000, 0x0000000709e00000| Untracked
|  62|0x000000070a000000, 0x000000070a000000, 0x000000070a200000|  0%| F|  |TAMS 0x000000070a000000, 0x000000070a000000| Untracked
|  63|0x000000070a200000, 0x000000070a200000, 0x000000070a400000|  0%| F|  |TAMS 0x000000070a200000, 0x000000070a200000| Untracked
|  64|0x000000070a400000, 0x000000070a400000, 0x000000070a600000|  0%| F|  |TAMS 0x000000070a400000, 0x000000070a400000| Untracked
|  65|0x000000070a600000, 0x000000070a600000, 0x000000070a800000|  0%| F|  |TAMS 0x000000070a600000, 0x000000070a600000| Untracked
|  66|0x000000070a800000, 0x000000070a800000, 0x000000070aa00000|  0%| F|  |TAMS 0x000000070a800000, 0x000000070a800000| Untracked
|  67|0x000000070aa00000, 0x000000070aa00000, 0x000000070ac00000|  0%| F|  |TAMS 0x000000070aa00000, 0x000000070aa00000| Untracked
|  68|0x000000070ac00000, 0x000000070ac00000, 0x000000070ae00000|  0%| F|  |TAMS 0x000000070ac00000, 0x000000070ac00000| Untracked
|  69|0x000000070ae00000, 0x000000070ae00000, 0x000000070b000000|  0%| F|  |TAMS 0x000000070ae00000, 0x000000070ae00000| Untracked
|  70|0x000000070b000000, 0x000000070b000000, 0x000000070b200000|  0%| F|  |TAMS 0x000000070b000000, 0x000000070b000000| Untracked
|  71|0x000000070b200000, 0x000000070b200000, 0x000000070b400000|  0%| F|  |TAMS 0x000000070b200000, 0x000000070b200000| Untracked
|  72|0x000000070b400000, 0x000000070b400000, 0x000000070b600000|  0%| F|  |TAMS 0x000000070b400000, 0x000000070b400000| Untracked
|  73|0x000000070b600000, 0x000000070b600000, 0x000000070b800000|  0%| F|  |TAMS 0x000000070b600000, 0x000000070b600000| Untracked
|  74|0x000000070b800000, 0x000000070b800000, 0x000000070ba00000|  0%| F|  |TAMS 0x000000070b800000, 0x000000070b800000| Untracked
|  75|0x000000070ba00000, 0x000000070ba00000, 0x000000070bc00000|  0%| F|  |TAMS 0x000000070ba00000, 0x000000070ba00000| Untracked
|  76|0x000000070bc00000, 0x000000070bc00000, 0x000000070be00000|  0%| F|  |TAMS 0x000000070bc00000, 0x000000070bc00000| Untracked
|  77|0x000000070be00000, 0x000000070be00000, 0x000000070c000000|  0%| F|  |TAMS 0x000000070be00000, 0x000000070be00000| Untracked
|  78|0x000000070c000000, 0x000000070c000000, 0x000000070c200000|  0%| F|  |TAMS 0x000000070c000000, 0x000000070c000000| Untracked
|  79|0x000000070c200000, 0x000000070c200000, 0x000000070c400000|  0%| F|  |TAMS 0x000000070c200000, 0x000000070c200000| Untracked
|  80|0x000000070c400000, 0x000000070c400000, 0x000000070c600000|  0%| F|  |TAMS 0x000000070c400000, 0x000000070c400000| Untracked
|  81|0x000000070c600000, 0x000000070c600000, 0x000000070c800000|  0%| F|  |TAMS 0x000000070c600000, 0x000000070c600000| Untracked
|  82|0x000000070c800000, 0x000000070c800000, 0x000000070ca00000|  0%| F|  |TAMS 0x000000070c800000, 0x000000070c800000| Untracked
|  83|0x000000070ca00000, 0x000000070ca00000, 0x000000070cc00000|  0%| F|  |TAMS 0x000000070ca00000, 0x000000070ca00000| Untracked
|  84|0x000000070cc00000, 0x000000070cc00000, 0x000000070ce00000|  0%| F|  |TAMS 0x000000070cc00000, 0x000000070cc00000| Untracked
|  85|0x000000070ce00000, 0x000000070ce00000, 0x000000070d000000|  0%| F|  |TAMS 0x000000070ce00000, 0x000000070ce00000| Untracked
|  86|0x000000070d000000, 0x000000070d000000, 0x000000070d200000|  0%| F|  |TAMS 0x000000070d000000, 0x000000070d000000| Untracked
|  87|0x000000070d200000, 0x000000070d200000, 0x000000070d400000|  0%| F|  |TAMS 0x000000070d200000, 0x000000070d200000| Untracked
|  88|0x000000070d400000, 0x000000070d400000, 0x000000070d600000|  0%| F|  |TAMS 0x000000070d400000, 0x000000070d400000| Untracked
|  89|0x000000070d600000, 0x000000070d600000, 0x000000070d800000|  0%| F|  |TAMS 0x000000070d600000, 0x000000070d600000| Untracked
|  90|0x000000070d800000, 0x000000070d800000, 0x000000070da00000|  0%| F|  |TAMS 0x000000070d800000, 0x000000070d800000| Untracked
|  91|0x000000070da00000, 0x000000070da00000, 0x000000070dc00000|  0%| F|  |TAMS 0x000000070da00000, 0x000000070da00000| Untracked
|  92|0x000000070dc00000, 0x000000070dc00000, 0x000000070de00000|  0%| F|  |TAMS 0x000000070dc00000, 0x000000070dc00000| Untracked
|  93|0x000000070de00000, 0x000000070de00000, 0x000000070e000000|  0%| F|  |TAMS 0x000000070de00000, 0x000000070de00000| Untracked
|  94|0x000000070e000000, 0x000000070e000000, 0x000000070e200000|  0%| F|  |TAMS 0x000000070e000000, 0x000000070e000000| Untracked
|  95|0x000000070e200000, 0x000000070e200000, 0x000000070e400000|  0%| F|  |TAMS 0x000000070e200000, 0x000000070e200000| Untracked
|  96|0x000000070e400000, 0x000000070e400000, 0x000000070e600000|  0%| F|  |TAMS 0x000000070e400000, 0x000000070e400000| Untracked
|  97|0x000000070e600000, 0x000000070e600000, 0x000000070e800000|  0%| F|  |TAMS 0x000000070e600000, 0x000000070e600000| Untracked
|  98|0x000000070e800000, 0x000000070e800000, 0x000000070ea00000|  0%| F|  |TAMS 0x000000070e800000, 0x000000070e800000| Untracked
|  99|0x000000070ea00000, 0x000000070ea00000, 0x000000070ec00000|  0%| F|  |TAMS 0x000000070ea00000, 0x000000070ea00000| Untracked
| 100|0x000000070ec00000, 0x000000070ec00000, 0x000000070ee00000|  0%| F|  |TAMS 0x000000070ec00000, 0x000000070ec00000| Untracked
| 101|0x000000070ee00000, 0x000000070ee00000, 0x000000070f000000|  0%| F|  |TAMS 0x000000070ee00000, 0x000000070ee00000| Untracked
| 102|0x000000070f000000, 0x000000070f000000, 0x000000070f200000|  0%| F|  |TAMS 0x000000070f000000, 0x000000070f000000| Untracked
| 103|0x000000070f200000, 0x000000070f200000, 0x000000070f400000|  0%| F|  |TAMS 0x000000070f200000, 0x000000070f200000| Untracked
| 104|0x000000070f400000, 0x000000070f400000, 0x000000070f600000|  0%| F|  |TAMS 0x000000070f400000, 0x000000070f400000| Untracked
| 105|0x000000070f600000, 0x000000070f600000, 0x000000070f800000|  0%| F|  |TAMS 0x000000070f600000, 0x000000070f600000| Untracked
| 106|0x000000070f800000, 0x000000070f800000, 0x000000070fa00000|  0%| F|  |TAMS 0x000000070f800000, 0x000000070f800000| Untracked
| 107|0x000000070fa00000, 0x000000070fa00000, 0x000000070fc00000|  0%| F|  |TAMS 0x000000070fa00000, 0x000000070fa00000| Untracked
| 108|0x000000070fc00000, 0x000000070fc00000, 0x000000070fe00000|  0%| F|  |TAMS 0x000000070fc00000, 0x000000070fc00000| Untracked
| 109|0x000000070fe00000, 0x000000070fe00000, 0x0000000710000000|  0%| F|  |TAMS 0x000000070fe00000, 0x000000070fe00000| Untracked
| 110|0x0000000710000000, 0x0000000710100800, 0x0000000710200000| 50%| E|  |TAMS 0x0000000710000000, 0x0000000710000000| Complete
| 111|0x0000000710200000, 0x0000000710400000, 0x0000000710400000|100%| E|CS|TAMS 0x0000000710200000, 0x0000000710200000| Complete
| 112|0x0000000710400000, 0x0000000710600000, 0x0000000710600000|100%| E|CS|TAMS 0x0000000710400000, 0x0000000710400000| Complete
| 113|0x0000000710600000, 0x0000000710800000, 0x0000000710800000|100%| E|CS|TAMS 0x0000000710600000, 0x0000000710600000| Complete
| 114|0x0000000710800000, 0x0000000710a00000, 0x0000000710a00000|100%| E|CS|TAMS 0x0000000710800000, 0x0000000710800000| Complete
| 115|0x0000000710a00000, 0x0000000710c00000, 0x0000000710c00000|100%| E|CS|TAMS 0x0000000710a00000, 0x0000000710a00000| Complete
| 116|0x0000000710c00000, 0x0000000710e00000, 0x0000000710e00000|100%| E|CS|TAMS 0x0000000710c00000, 0x0000000710c00000| Complete
| 117|0x0000000710e00000, 0x0000000711000000, 0x0000000711000000|100%| E|CS|TAMS 0x0000000710e00000, 0x0000000710e00000| Complete
| 118|0x0000000711000000, 0x0000000711200000, 0x0000000711200000|100%| E|CS|TAMS 0x0000000711000000, 0x0000000711000000| Complete
| 119|0x0000000711200000, 0x0000000711400000, 0x0000000711400000|100%| E|CS|TAMS 0x0000000711200000, 0x0000000711200000| Complete
| 120|0x0000000711400000, 0x0000000711600000, 0x0000000711600000|100%| E|CS|TAMS 0x0000000711400000, 0x0000000711400000| Complete
| 121|0x0000000711600000, 0x0000000711800000, 0x0000000711800000|100%| E|CS|TAMS 0x0000000711600000, 0x0000000711600000| Complete
| 122|0x0000000711800000, 0x0000000711a00000, 0x0000000711a00000|100%| E|CS|TAMS 0x0000000711800000, 0x0000000711800000| Complete
| 123|0x0000000711a00000, 0x0000000711c00000, 0x0000000711c00000|100%| E|CS|TAMS 0x0000000711a00000, 0x0000000711a00000| Complete
| 124|0x0000000711c00000, 0x0000000711e00000, 0x0000000711e00000|100%| E|CS|TAMS 0x0000000711c00000, 0x0000000711c00000| Complete
| 125|0x0000000711e00000, 0x0000000712000000, 0x0000000712000000|100%| E|CS|TAMS 0x0000000711e00000, 0x0000000711e00000| Complete
| 126|0x0000000712000000, 0x0000000712200000, 0x0000000712200000|100%| E|CS|TAMS 0x0000000712000000, 0x0000000712000000| Complete

我们可以在输出中清楚的观察到:

总堆大小 —— 260096K
GC算法 —— Garbage First
区大小 —— 2048K
区总数 —— 126
Eden区总数 —— 18
Survivor区总数 —— 1
大部分(区域)都是Free的,可以被用于老年代或者大对象区域。(因为大部分对象都是短期存活的)

随着我们持续的创建对象,我们可以看到eden和survivor区域被填满,并且成为了回收集的一部分。无论区域被标记还是被添加到回收集,它们都是下一次GC周期考虑的目标。

标签的缩写:
E=young(eden),
S=young(survivor),
O=old,
HS=大对象(starts),
HC=大对象(continues),
CS=回收集,
F=空闲,
OA=open archive,
CA=closed archive,
TAMS=top-at-mark-start

命令行参数

使用如下命令编译并且运行代码:

javac MemoryVerification.java
java -Xms1g -Xmx1g -XX:+UseG1GC G1GCVerification

我们传入了-XX:+UseG1GC,所以JVM会使用G1GC作为运行程序时的垃圾回收算法。

使用jstatjconsole工具分析内存,它们内置在JDK中。

jstat命令

我们将使用java默认自带的jstat命令。运行jps命令列出系统中所有运行的java进程,查看名为G1GCVerification的进程id。

运行下面的jstat命令(末尾的2000将每隔2000ms持续运行这个命令)

jstat -gc <pid-of-memory-verification-program> 2000

img

这张图片展示了(combined/added这里没看懂)所有Eden、Survivor 0、Survivor 1和老年代块的空间,我们可以看到EU(Eden利用率)在持续增长。

Jconsole命令

运行下面的jconsole命令:

jconsole <pid-of-memory-verification-program>

img

在运行jconsole命令后,将在windows中打开Java的监视器UI:

img

在这里,我们可以看到当前程序正在使用G1GC,而1GB存储器则按照配置分配给JVM。

现在我们将讨论如何处理大于G1GC中一个块大小的对象。

巨大对象

在G1GC中,任何大于一半区域大小的对象都被认为是巨大对象(Humongous object)。

  • 巨大对象太大了,无法装到G1GC为常规对象使用的常见的内存区域中
  • 所以,G1GC以不同的方式处理巨大对象
  • G1GC将巨大对象共同放在一个特殊的内存区域中,而不是将它们拆成更小的部分
  • 就像常规对象一样,巨大对象可能随着时间变得没用了,或者说成为垃圾了
  • G1GC在垃圾回收过程中也会检查它们是否仍然被需要。如果巨大对象已经没用了,G1GC可以清理掉它的内存
  • G1GC很小心地处理巨大对象,将它们放在一个单独区域以避免碎片以及确保它们的GC尽可能高效
  • 为了减少复制开销,巨大对象不会引入任何evacuation暂停。fullgc周期会原地压缩所有巨大对象

G1GC属性

下面是G1GC的属性,包含它们的用处以及默认值:

XX:+UseG1GC

  • Description: 开启G1GC作为垃圾回收器
  • Default Value: 未使用(貌似现在已经是默认启用)

XX:MaxGCPauseMillis

  • Description: 设置最大目标暂停时间
  • Default Value: 200ms.

XX:G1HeapRegionSize

  • Description: 定义单个G1GC区域的大小
  • Default Value: 根据堆大小自动计算

XX:InitiatingHeapOccupancyPercent

  • Description: 基于堆占用率来控制G1GC何时开始它的GC周期
  • Default Value: 45%.

XX:ParallelGCThreads

  • Description: 控制G1GC使用的并行线程数量
  • Default Value: 当前处理器数

XX:ConcGCThreads

  • Description: 对于特定任务指定并发GC线程数量
  • Default Value: 当前处理器数量

XX:G1ReservePercent

  • Description: 为GC过载保留多少堆内存的比例
  • Default Value: 堆大小10%

XX:G1HeapWastePercent

  • Description: 用于控制一个区域中可以浪费多少百分比的内存,G1才会考虑它是可收回的
  • Default Value: 5%.

XX:G1MixedGCLiveThresholdPercent

  • Description: 设置一个区域中存活数据的比例必须到达多少才会被mixed gc考虑
  • Default Value: 65%.

XX:MaxTenuringThreshold

  • Description: 设置年轻代中对象的最大保留阈值
  • Default Value: 15.

总结

G1GC算法使用了完全不同的方式,并且它是最适合那些需要大量JVM内存的程序。去分析你正在运行的企业级应用程序的JVM指标,并去理解G1GC如何清理内存吧!玩得愉快!

如果你对CMS如何工作感兴趣,请阅读这个文章

posted @ 2024-05-29 11:13  yudoge  阅读(49)  评论(0编辑  收藏  举报