JVM基础系列:GC日志设置

  在观察JVM GC时,我们需要看得懂GC日志,并且知道相关的参数配置。

  我们以下面的这个Demo为例子去设置GC日志参数(需要 javac 生成class文件)

public class GCDemo {
    public static  void main (String[] agrs) {
        
        byte[] b = new byte[4 * 1024 * 1024];
        System.out.println("first allocate");
        b = new byte[4 * 1024 * 1024];
        System.out.println("second allocate");
  }
}

  在上面的程序中,我们两次分配4M的内存空间。为了人为制造GC,我们启动时的JVM参数固定为一下几个参数

-XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8
  • -XX:+UseSerialGC 表示强制使用串行年轻代、老年代收集器组合
  • -Xms20M 表示堆空间初始大小为20M
  • -Xmx20M 表示堆空间最大大小为20M
  • -Xmn10M 表示新生代大小为10M
  • +XX:SurvivorRatio=8 表示Eden:Survivor=8:1

  经过上面设置,此时我们的堆空间内存比例情况如下:Eden区 8M,From区 1M,To区 1M,老年代 10M。

  下面是有关GC日志的参数设置

  打印GC日志

  在GC日志参数中,最简单的一个参数就是打印GC日志:-XX:PrintGC。我们用下面的命令运行程序:

java -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC GCDemo

  输出结果:

 

 

   可以看到程序在第二次分配数组空间发生了GC,并且把GC前后以及堆空间大小都打印了出来。该日志显示GC前堆空间使用量为5244K(4M左右),GC后堆空间使用量为4783K,当前可用堆大小为19456K。

  但你会发现使用PrintGC 参数打印出来的日志比较简单,无法查看更详细的信息。如果你要查看更详细的信息,那么就需要下面这个参数。

  打印详细GC日志

  如果要查看更详细的GC日志,那么就要使用-XX:PrintGCDetails 参数。下面我们使用该参数运行程序:

java -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails GCDemo

  输出结果:

 

 

   从上面的日志可以看出,该参数答应出更加详细的GC信息,包括年轻代的信息、堆空间信息、永久代(如果有的话)的信息。

 

 

   该参数还是在退出之前打印这个堆的详细信息:

 

 

   GC前后打印堆信息

  上面的命令基本上可以应付90%的使用场景了,但是有时候我们在GC前后还想要获取更详细的信息。那么我们可以使用PrintHeapAtGC 参数,该参数会在GC前后打印堆信息。

  使用下面命令运行程序:

java +XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintHeapAtGC GCDemo

  输出结果:

  通过这个参数,我们可以详细了解每次GC时堆空间的详细信息。

  打印GC发生时间 -XX:+PrintGCTimeStamps

  这个顾名思义,就是在每次GC日志的前面加上一个时间戳。这个时间戳表示JVM启动后到现在所逝去的时间。

  使用下面的参数运行程序:

java -XX:UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC -XX:+PrintGCTimeStamps GCDemo

  输出结果:

 

 

   上面日志第二行中”0.080“就该GC发生时间(程序启动到GC发生的时间)

  -XX:+PrintGCApplicationConcurrentTime 打印应用程序执行使时间

  使用下面的命令运行程序:

java -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC -XX:+PrintGCApplicationConcurrentTime GCDemo

  运行结果:

 

   -XX:+PrintGCApplicationStoppedTime 打印应用由于GC而发生的停顿时间

java -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC -XX:PrintGCApplicationStoppedTime GCDemo

  运行结果:

 

   可以看到最后一行打印出因为GC而暂停的时间。

  保存GC日志-Xloggc

  这个参数可以将GC日志输出到文件中保存起来。

java -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails -XX:+PrintReferenceGC -Xloggc:gc.log GCDemo

  运行之后在本项目目录生成一个gc.log文件,打开该文件,可以看到堆的相关信息,以及GC的信息  :

 

   总结

  除了是上面这些参数,还有可以查看弱引用的参数:-XX:+PrintReferenceGC,他跟踪软引用,弱引用,虚引用和Finallize队列,但是这些使用场景比较罕见,基本上掌握上面几个常用的GC日志参数就足够排查使用,最重要是要弄清楚每个参数的作用和用法。

  最后一个列表总结下:

参数含义
-XX:PrintGC 打印GC日志
-XX:+PrintGCDetails 打印详细的GC日志。还会在退出前打印堆的详细信息。
-XX:+PrintHeapAtGC 每次GC前后打印堆信息。
-XX:+PrintGCTimeStamps 打印GC发生的时间。
-XX:+PrintGCApplicationConcurrentTime 打印应用程序的执行时间
-XX:+PrintGCApplicationStoppedTime 打印应用由于GC而产生的停顿时间
-XX:+PrintReferenceGC 跟踪软引用、弱引用、虚引用和Finallize队列。
-XLoggc 将GC日志以文件形式输出
posted @ 2022-10-11 10:15  梅晓煜  阅读(1373)  评论(0)    收藏  举报