`

JVM GC总结

阅读更多

JVM GC总结

 

参考 林昊 <分布式Java应用基础与实践>

 

1. 首先需要弄清JVM的内存结构,参考: 【转】JVM内存结构  

 

2. JVM GC 大致可分为三类:Minor GC,Major GC和Full GC.

 

   Minor GC指堆内存 新生代上发生的垃圾回收.

   

   Major GC是指堆内存的旧生代 和 非堆内存的持久代 上发生的垃圾回收.

   

   因为通常发生Major GC时至少要进行一次的Minor GC,

   所以将这种Minor GC和Major GC同时发生的GC称为Full GC.

   需要注意的是,并不是所有的Major都会导致Full GC.

   (比如,在 ParallelScavenge 收集器的收集策略里,就有直接进行 Major GC 的策略选择过程)

   通常可以任务发生Major GC时就是发生Full GC之时.

   

3 Minor GC 和 Major GC 都有几种不同的方式可选择.

 

3.1 新生代可用的GC(Minor Gc)

 

    Minor GC 采用复制算法,将存活的对象从Eden和S0(或S1)拷贝到S1(或S0)上.

 

3.1.1 串行GC(Serial GC)

   

      对象在从存活区(S0或S1)拷贝到旧生代之前经历的Minor次数由-XX:MaxTenuringThreshold控制

      

      Eden 和 Survivor的空间大小受参数:-XX:SurvivorRatio控制.

      SurvivorRatio = Eden 空间 / 一个Survivor的空间

      比如新生代-Xmn10M,-XX:SurvivorRatio = 8,则Eden为8M,每个Survivor为1M.

      

      通过配置JVM参数:-XX:PretenureSizeThreshold

      使得对象大小超过这个数值时,对象直接在旧生代上分配空间.

      

      Serial GC 在整个扫描和复制过程中都采用单线程的方式来进行,更加适用于单CPU,新生代空间较小,

      以及对暂停时间要求不是非常高的应用.是client级别(CPU核数小于2或物理内存小于2GB)或32位

      windows机器上默认的GC方式.

      

      使用,-XX:+UseSerialGC参数强制使用Serial GC.

  

3.1.2 并行回收GC(Parallel Scavenge)

      

      Eden S0 S1大小受InitialSurvivorRatio控制,JDK1.6之后也可以通过SurvivorRatio,但并行回收GC

      将此值+2然后赋给InitialSurvivorRatio.

      (1) InitialSurvivorRatio 和 SurvivorRatio都不设置

          用-Xms20m -Xmx20m -Xmn10m -XX:+UseParallelGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGC

          执行,则Eden为7.5M,S0和S1 为1.25M,则7.5/1.25 = 6.

      (2) 只配置SurvivorRatio = 10

          用-Xms20m -Xmx20m -Xmn12m -XX:+UseParallelGC -XX:SurvivorRatio=10 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGC

          此时 Eden =10M,S0和S1 为1M,则10 / 1 = 10 等于设置的-XX:SurvivorRatio=10

      (3) 只设置 InitialSurvivorRatio = 10

          用-Xms20m -Xmx20m -Xmn10m -XX:+UseParallelGC -XX:InitialSurvivorRatio=10 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGC

          此时Eden =8M,S0和S1 为1M,8 / 1 = 8 = InitialSurvivorRatio - 2

      (4) 同时设置SurvivorRatio = 10 和 InitialSurvivorRatio = 10

          用-Xms20m -Xmx20m -Xmn10m -XX:+UseParallelGC -XX:SurvivorRatio=10 -XX:InitialSurvivorRatio=10 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGC

      因此,采用并行回收GC时: 

      如果没有配置SurvivorRatio和InitialSurvivorRatio,则默认值,Eden / Survivor = 6; 

      如果只配置了SurvivorRatio = 10则以这个为准Eden / Survivor = SurvivorRatio ;

      如果只配置了InitialSurvivorRatio = 10 则 Eden / Survivor = InitialSurvivorRatio - 2;

      如果同时配置了InitialSurvivorRatio 和 SurvivorRatio,则以InitialSurvivorRatio 为准,Eden / Survivor = InitialSurvivorRatio - 2

      另外,使用并行回收GC时,虚拟机会根据运行情况动态调整Eden S0 和S1的大小,上面的值只是设置初始值,

      可用通过使用-XX:-UseAdaptiveSizePolicy固定Eden S0和S1的大小为上面设置的值.

      

      对于对象是否直接在旧生代上分配不受-XX:PretenureSizeThreshold控制,而是在Eden空间不够情况下,

      当对象大小大于等于Eden大小一半时,即在旧生代上分配.

      

      并行回收GC(Parallel Scavenge)也是采用复制算法,但是在扫描和复制是均采用多线程方式,且并行回收GC为大的

      新生代回收做了很多优化.在多CPU机器上其回收的耗时比串行方式短,适用于多CPU,对暂停时间要求短的应用上.

      并行回收GC是server级别(CPU核数超过2且物理内存超过2GB)的机器(32位window除外)上默认的GC方式.并行线程数量

      在CPU核数小于等于8时,即为CPU核数,当CPU核数多于8时,计算公式为:3 + (CPU核数 * 5) / 8,也可通过

      -XX:ParallelGCThreads = 4 来强制制定.

      

      使用-XX:+UseParallelGC强制使用并行回收GC(Parallel Scavenge)

 

3.1.3并行GC(ParNew)

  

     Eden 和S0 S1的空间分配方式和串行GC采用的方式相同.

     

     并行GC方式必须与旧生代的CMS GC方式配合使用. CMS GC方式要求 Minor GC需采用并行方式并做一些特殊处理

     (并行回收方式没有这种特殊处理),因此CMS GC只能和 并行GC(ParNew)一同使用.

     同时,也是因为并行GC(ParNew)的特殊处理,是的Major GC的并行回收方式不能和ParNew GC方式同时使用.

     

     使用-XX:+UsePaNewGC强制使用并行GC(ParNew)

 

3.2 旧生代和持久代可用的GC

    

    JDK提供了串行,并行及并发三种GC来对就生代及持久代对象所占用的内存进行回收.

    

3.2.1 串行GC

 

     串行基于Mark - Sweep - Compact实现,结合了Mark - Sweep, Mark - Compact做了一些改进.

     过程:

     (1) 从根集合对象扫描,按照三色着色啊法哪个是对对象进行标识;

     (2) 遍历旧生代或持久代,找出未标记对象,并回收其内存;

     (3) 执行活动压缩(Sliding Compaction)

     

     串行执行过程中需要暂停应用.采用单线程方式,通常需要耗费较长时间,通过

     -XX:+PrintGCApplicationStopTime来查看GC造成的暂停时间.

     

     通过-XX:+UseSerialGC强制制定该方式.

     

3.2.1 并行GC 

 

      基于 Mark - Compact 实现.

      过程:

      (1) 将代空间分区域(区域个数和并行GC的线程数相同),然后使用多线程扫描标记着色对象,

          同时更新其所在region的存活大小及位置.

      (2) 确定压缩移动的region(通常旧生代左边存放的是一些活跃对象(不容易死的)

          因此这部分对象所在的region通常不压缩)的region源和region目的地.

          该过程目前为单线程进行.

      (3) 基于(2)中的分析信息进行对象的移动和region的回收.

          

      并行GC与之前的串行GC相比,大部分时候是多线程的,对应用造成的暂停时间会缩短.

      但是由于旧生代较大,再扫描和标识对象上需要话费较长时间.

      

      通过 -XX:+UseParallelGC 或 -XX:+UseParallelOldGC 来强制制定.

      两者区别:

      -XX:+UseParallelOldGC同时激活新生代并行垃圾回收和老年代的并行垃圾回收,

      亦即,Minor GC和Full GC都是多线程的;

      -XX:+UseParallelGC只会激活新生代的并行垃圾回收(旧生代使用的是Serial GC)。

      也就是使用了-XX:+UseParallelOldGC会自动激活-XX:+UseParallelGC。

      

      UseParallelGC would result in parallel young + serial old  and 

      UseParallelOldGC in parrallel young + parralel old gcs.

      

      参考: 

      oracle官方文档:

      [读书笔记]《Java Performance》GC(1)

      use UseParallelOldGC instead of UseParallelGC #1105

      Should we use UseParallelOldGC instead of UseParallelGC in hornetq user manual?:

 

3.2.3 并发(CMS Concurrent Mark-Sweep GC)  

 

     基于Mark-Sweep方式, 该方式可以减少GC应用暂停时间.

     Mark-Sweep 可能会产生内存碎片.

     并行 与 并发 区别在于,并行时 只有 垃圾回收线程运行,应用暂停了.

     而并发 时 应用线程 和 垃圾回收线程可同时执行.

     过程:

     (1) 第一次标记,暂停应用,只标记存活的根对象(速度快,暂停时间短,因为根对象毕竟不太多)

     (2) 并发标记 根据(1)的根对象,标记所有从根对象能够引用到的对象(耗时操作,并发进行,不停应用)

     (3) 重新标记,暂停应用,重新标记在步骤(2)进行时可能出现的新的类似与(1)中的根对象

         以及该根对象可达的所有存活对象,并对引用关系可能发生的变化做一些额外处理

         (需要处理的对象也是少数,因而速度快,暂停时间短)

     (4) 并发收集(耗时操作,并发进行,不停应用)

     

     虽然有两次暂停,但是暂停时间都比较短,耗时长的都是并发执行的.

     

     CMS方式的GC之后通常会产生内存碎片,因此CMS提供了内存碎片整理功能.

     这个内存整理功能在没有使用CMS时也可以使用,可以通过

     -XX:+UseCMSCompactAtFullCollection 在每次full gc之后都进行内存整理.

     也可以指定-XX:+CMSFullGCsBeforeCompact=3来指定在若干次full gc之后

     进行内存碎片整理.

     

     使用:-XX:+UseComcMarkSweepGC来强制使用CMS 方式的GC,默认开启的线程数为:

     (并行 GC线程数 + 3) / 4,可通过-XX:+ParallelCMSThreads=10来强制指定.

         

     CMS GC的触发条件不是旧生代满了,而是当旧生代已用空间达到参数: 

     -XX:CMSInitiatingOccupancyFraction设置的百分比.比如,默认

     -XX:CMSInitiatingOccupancyFraction=68%,则旧生代总工1000M,在已用空间达680M时

     触发CMS GC.还有一种方式,是JVM自行触发,指JVM根据之前GC的频率及旧生代的增长趋势

     来评估决定什么时候执行CMS GC,如果不希望JVM自行触发CMS GC,可以设置参数:

     -XX:+UseCMSInitiatingOccupancyOnly=true设置.

     

     可以通过设置参数-XX:+CMSPermGenSweepingEnabled使得持久代的GC也使用CMS.

     持久代GC默认是使用Full GC.

     

     

4. GC触发条件

 

   (1) 通常JVM在为对象分配空间是在新生代的Eden部分分配的.

       当Eden的剩余空间已经不足以放下一个新对象时会触发Minor GC.

   

   (2) 发生Minor GC时,Eden和S0(或S1)上的存活对象会被拷贝到S1(或S0)上.

       当S1(或S0)的剩余空间不足以容纳要拷贝的对象时,对象被直接拷贝到

       旧生代上;

       

       当经历了若干次(具体的次数可以通过-XX:MaxTenuringThreshold参数配置,这里配置的是最大值,

       也就是说,假如该值配置的5,则可能经历3次Minor GC后,对象就被拷贝到旧生代了,但最多不超过5次)

       的Minor GC时,S1(或S0)上仍然存活的对象会被拷贝到旧生代上;

       

       当Minor GC采用串行GC时,可以通过配置JVM参数:-XX:PretenureSizeThreshold

       使得对象大小超过这个数值时,对象直接在旧生代上分配空间.

       

       当Minor GC采用并行回收(Parallel Scavenge)GC,在Eden空间不够,在要分配空间的对象大小

       超过Eden空间一半时,直接在旧生代上分配(不受-XX:PretenureSizeThreshold这个参数控制了).

       

   (3) 当旧生代上空间不足以容纳要拷贝的对象时,会触发 Major GC.

       CMS GC的触发条件不是旧生代满了,而是当旧生代已用空间达到参数: 

       -XX:CMSInitiatingOccupancyFraction设置的百分比.比如,默认

       -XX:CMSInitiatingOccupancyFraction=68%,则旧生代总工1000M,在已用空间达680M时

       触发CMS GC.还有一种方式,是JVM自行触发,指JVM根据之前GC的频率及旧生代的增长趋势

       来评估决定什么时候执行CMS GC,如果不希望JVM自行触发CMS GC,可以设置参数:

       -XX:+UseCMSInitiatingOccupancyOnly=true设置.

   

   (4) 在持久代空间不足时也触发Full GC(比如Load一个class后导致持久代空间不足,或者反射调用).

       可以通过设置参数-XX:+CMSPermGenSweepingEnabled,使用CMS收集持久代的类.

       

   (5) Full Gc 触发情况

   

      a. 代码中显示执行System.gc();

      b. 旧生代空间不足

      c. 持久代空间满了(没有设置-XX:+CMSPermGenSweepingEnabled)

      c. CMS GC时出现promotion failed 和 concurrent mode failure

         promotion failed是在执行Minor GC时,Survivor放不下,而此时旧生代也放不下时造成的

         concurrent mode failure 是在执行CMS GC的过程中,同时有对象要放入旧生代,此时旧生代

         空间不足造成的.

      d. 统计得到Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间.

    

5. 示例代码

 

   使用myeclipse测试代码,通过Run -> Open run dialogue 打开运行对话框,在

   Arguments选项卡的vmarguments中设置JVM执行参数:

   常用参数:

    -Xms20m (堆内存最小空间) 

    -Xmx20m (堆内存最大空间) 

    -Xmn10m (堆内存 新生代空间) 

-XX:SurvivorRatio=10(eden 和 Survivor空间大小比值,默认值8) 

-XX:InitialSurvivorRatio=10(并行GC时用到)

-XX:+UseConcMarkSweepGC(使用CMS GC)  

-verbose:gc 

-XX:+PrintGCDetails (打印GC详细信息)

-XX:+PrintGC 

-XX:+PrintGCTimeStamps (打印GC信息时打印相对时间)

-XX:+PrintGCDateStamps (打印GC信息时,打印详细日期时间)

-XX:+UseCMSCompactAtFullCollection (Full GC时使用GMS 整理内存碎片)

-XX:+PrintGCApplicationStoppedTime (打印GC时应用暂停时间)

-XX:+PrintGCApplicationConcurrentTime (GC之间运行了多少时间)

-Xloggc:D:/D/gc.log (将GC日志输出到文件,指定这个参数之后,控制台中不再打印GC日志了)

 

5.1 Minor GC触发示例:Eden 空间不足时触发Minor GC

 

   

package jvm;

/**
 * 
 * 1. Eden 空间不足时触发Minor GC  
 * JVM参数:
 * -Xms40m
 * -Xmx40m
 * -Xmn16m
 * -XX:+UseParallelGC
 * -verbose:gc 
 * -XX:+PrintGCDetails
 * 此时Eden为12M,Survivor都是2M.
 * 
 * 输出信息如下:
 * 
mino gc should happen
[GC [PSYoungGen: 11509K->1200K(14336K)] 11509K->1200K(38912K), 0.0086913 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
mino gc should happen
[GC [PSYoungGen: 12589K->1184K(14336K)] 12589K->1184K(38912K), 0.0043232 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 14336K, used 2453K [0x08200000, 0x09200000, 0x09200000)
  eden space 12288K, 10% used [0x08200000,0x0833d780,0x08e00000)
  from space 2048K, 57% used [0x09000000,0x09128050,0x09200000)
  to   space 2048K, 0% used [0x08e00000,0x08e00000,0x09000000)
 PSOldGen        total 24576K, used 0K [0x06a00000, 0x08200000, 0x08200000)
  object space 24576K, 0% used [0x06a00000,0x06a00000,0x08200000)
 PSPermGen       total 12288K, used 2087K [0x02a00000, 0x03600000, 0x06a00000)
  object space 12288K, 16% used [0x02a00000,0x02c09c10,0x03600000)
 *
 *使用 jstat工具查看可以看到YGC 发生了2次,耗时分别为19毫秒和26毫秒.
 *
 >jstat -gcutil 110788 2000
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  0.00  87.90  22.17   0.00  46.22      1    0.019     0    0.000    0.019
  0.00  87.90  30.51   0.00  46.22      1    0.019     0    0.000    0.019
  0.00  87.90  40.88   0.00  46.23      1    0.019     0    0.000    0.019
  0.00  87.90  49.21   0.00  46.23      1    0.019     0    0.000    0.019
  0.00  87.90  58.57   0.00  46.26      1    0.019     0    0.000    0.019
  0.00  87.90  58.57   0.00  46.26      1    0.019     0    0.000    0.019
  0.00  87.90  59.59   0.00  46.26      1    0.019     0    0.000    0.019
  0.00  87.90  59.59   0.00  46.26      1    0.019     0    0.000    0.019
  0.00  87.90  60.61   0.00  46.27      1    0.019     0    0.000    0.019
  0.00  87.90  60.61   0.00  46.27      1    0.019     0    0.000    0.019
  0.00  87.90  62.65   0.00  46.32      1    0.019     0    0.000    0.019
  0.00  87.90  62.65   0.00  46.32      1    0.019     0    0.000    0.019
  0.00  87.90  63.67   0.00  46.35      1    0.019     0    0.000    0.019
  0.00  87.90  63.67   0.00  46.36      1    0.019     0    0.000    0.019
  0.00  87.90  64.69   0.00  46.38      1    0.019     0    0.000    0.019
  0.00  87.90  73.03   0.00  46.38      1    0.019     0    0.000    0.019
  0.00  87.90  74.05   0.00  46.40      1    0.019     0    0.000    0.019
  0.00  87.90  82.38   0.00  46.40      1    0.019     0    0.000    0.019
  0.00  87.90  92.76   0.00  46.43      1    0.019     0    0.000    0.019
 87.12   0.00   8.33   0.00  46.43      2    0.026     0    0.000    0.026
 87.12   0.00  20.70   0.00  46.48      2    0.026     0    0.000    0.026
 87.12   0.00  29.03   0.00  46.48      2    0.026     0    0.000    0.026
 87.12   0.00  38.19   0.00  46.53      2    0.026     0    0.000    0.026
 87.12   0.00  46.52   0.00  46.53      2    0.026     0    0.000    0.026
 87.12   0.00  56.50   0.00  46.61      2    0.026     0    0.000    0.026
 87.12   0.00  64.84   0.00  46.61      2    0.026     0    0.000    0.026
 87.12   0.00  74.82   0.00  46.70      2    0.026     0    0.000    0.026
 87.12   0.00  74.82   0.00  46.70      2    0.026     0    0.000    0.026
 87.12   0.00  79.29   0.00  46.80      2    0.026     0    0.000    0.026
 87.12   0.00  79.29   0.00  46.80      2    0.026     0    0.000    0.026
 87.12   0.00  80.04   0.00  46.80      2    0.026     0    0.000    0.026
 87.12   0.00  80.04   0.00  46.80      2    0.026     0    0.000    0.026
 87.12   0.00  81.55   0.00  46.81      2    0.026     0    0.000    0.026
 87.12   0.00  81.55   0.00  46.81      2    0.026     0    0.000    0.026
 87.12   0.00  82.32   0.00  46.81      2    0.026     0    0.000    0.026
 87.12   0.00  82.32   0.00  46.81      2    0.026     0    0.000    0.026
 87.12   0.00  83.84   0.00  46.81      2    0.026     0    0.000    0.026
 87.12   0.00  92.18   0.00  46.81      2    0.026     0    0.000    0.026
 87.12   0.00  92.93   0.00  46.82      2    0.026     0    0.000    0.026
 */

public class MinorGCDemo
{
  private static void happenMinorGC(int happenMinorGCIndex) throws Exception
  {
    for(int i=0;i<happenMinorGCIndex;i++)
    {
      if(i==happenMinorGCIndex - 1)
      {
        Thread.sleep(20000);
        System.out.println("minor gc should happen");
      }
      new MemoryObject(1024 * 1024);
      Thread.sleep(2000);
    }
  }
  
  public static void main(String[] args) throws Exception
  {
    MemoryObject object = new MemoryObject(1024 * 1024);//占用1M空间的对象
    for(int i=0;i<2;i++)
    {
      happenMinorGC(11); 
      //第一次分配了11个1M 加上之前分配的1M在分配第11个时,
      //达到eden的最大空间12M,输出minor gc should happen
      //后进行Minor GC
      Thread.sleep(2000);
    }
  }
}

class MemoryObject
{
  private byte[] bytes;
  
  public MemoryObject(int objectSize)
  {
    this.bytes = new byte[objectSize];
  }
}

 

 

5.2 Minor Gc时,survivor 空间不足,对象直接进入旧生代.    

  

package jvm;

/**
 * 
 * 2. Minor Gc时,survivor 空间不足,对象直接进入旧生代.
 * 
 * JVM参数:
 * -Xms40m
 * -Xmx40m
 * -Xmn16m
 * -XX:+UseParallelGC
 * -verbose:gc 
 * -XX:+PrintGCDetails
 *运行结果如下,其中PSOldGen        total 24576K, used 2048K [0x06a00000, 0x08200000, 0x08200000) 说明旧生代已占有2M空间
 *minor gc should happen
[GC [PSYoungGen: 11509K->1200K(14336K)] 11509K->3248K(38912K), 0.0115163 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 
Heap
 PSYoungGen      total 14336K, used 2469K [0x08200000, 0x09200000, 0x09200000)
  eden space 12288K, 10% used [0x08200000,0x0833d780,0x08e00000)
  from space 2048K, 58% used [0x08e00000,0x08f2c050,0x09000000)
  to   space 2048K, 0% used [0x09000000,0x09000000,0x09200000)
 PSOldGen        total 24576K, used 2048K [0x06a00000, 0x08200000, 0x08200000)
  object space 24576K, 8% used [0x06a00000,0x06c00010,0x08200000)
 PSPermGen       total 12288K, used 2087K [0x02a00000, 0x03600000, 0x06a00000)
  object space 12288K, 16% used [0x02a00000,0x02c09c48,0x03600000)
  
  jstat输出为:
  C:\Documents and Settings\10106511>jstat -gcutil 108148 2000
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00  90.04   0.00  46.21      0    0.000     0    0.000    0.000
  0.00   0.00  98.38   0.00  46.21      0    0.000     0    0.000    0.000
  0.00   0.00  98.38   0.00  46.24      0    0.000     0    0.000    0.000
  0.00   0.00  98.38   0.00  46.24      0    0.000     0    0.000    0.000
  0.00  89.07  12.62   8.33  46.26      1    0.015     0    0.000    0.015
  0.00  89.07  12.62   8.33  46.26      1    0.015     0    0.000    0.015
  0.00  89.07  23.24   8.33  46.28      1    0.015     0    0.000    0.015
  0.00  89.07  23.24   8.33  46.28      1    0.015     0    0.000    0.015
  0.00  89.07  24.51   8.33  46.32      1    0.015     0    0.000    0.015
  可以看到进行了一次Minor(YGC由0到1后) O字段从0到8.33%,表对象被复制到旧生代了.
 */
public class MinorSurvivorDemo
{
  private static void happenMinorGC(int happenMinorGCIndex) throws Exception
  {
    for(int i=0;i<happenMinorGCIndex;i++)
    {
      if(i==happenMinorGCIndex - 1)
      {
        Thread.sleep(2000);
        System.out.println("minor gc should happen");
      }
      new MemoryObject(1024 * 1024);
    }
  }
  
  public static void main(String[] args) throws Exception
  {
    MemoryObject object = new MemoryObject(1024 * 1024);//1M
    MemoryObject object2 = new MemoryObject(1024 * 1024 * 2);//2M
    happenMinorGC(9);
    //分配到第九个对象时,Eden满了(12M),导致GC,复制对象到Survivor时,先复制1M的(达到Survivor的空间了),
    //导致Survivor满了,然后将2M对象复制到旧生代.
    Thread.sleep(2000);
  }
}

 

 

5.3 测试使用不同GC方式时,输出的GC日志格式不同

package jvm;

/**
 * 
 * 测试使用不同GC方式时,输出的GC日志格式不同
 * 
 * 1. 使用串行GC -XX:+UseSerialGC
 *   vm参数如下:
-Xms40m
-Xmx40m
-Xmn16m
-XX:+UseSerialGC
-XX:SurvivorRatio=6
-verbose:gc 
-XX:+PrintGC
-XX:+PrintGCDetails
 * 此时Eden为12M,Survivor都是2M.
 *输出信息:
 *minor gc should happen
[GC [DefNew: 11509K->1173K(14336K), 0.0045310 secs] 11509K->1173K(38912K), 0.0045777 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
...
表示 使用-XX:+UseSerialGC时,GC日志中前缀使用的是DefNew
[DefNew: 11509K->1173K(14336K), 0.0045310 secs] 表示 Minor GC使得新生代已用空间从11509K变成1173K,可用空间14336
11509K->1173K(38912K) 表示GC使得堆空间的已用空间从11509K变成1173K,总可用空间为(38912K)
0.0045777 secs 表示本次GC总耗时.
[Times: user=0.00 sys=0.00, real=0.00 secs]  表示GC时CPU耗时占 CPU user和sys的百分比,以及总耗时

2.使用并行回收GC -XX:+UseParallelGC
*   vm参数如下:
-Xms40m
-Xmx40m
-Xmn16m
-XX:+UseParallelGC
-verbose:gc 
-XX:+PrintGC
-XX:+PrintGCDetails
输出:
minor gc should happen
[GC [PSYoungGen: 11509K->1200K(14336K)] 11509K->3248K(38912K), 0.0049179 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
.....

3.使用并行GC -XX:+UseParNewGC
*   vm参数如下:
-Xms40m
-Xmx40m
-Xmn16m
-XX:+UseParNewGC
-XX:SurvivorRatio=6
-verbose:gc 
-XX:+PrintGC
-XX:+PrintGCDetails
输出为:
minor gc should happen
[GC [DefNew: 11509K->1173K(14336K), 0.0034538 secs] 11509K->1173K(38912K), 0.0035021 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
...
由 DefNew 可知,使用-XX:+UseParNewGC时,Minor GC使用的是串行方式

4. 使用并行GC -XX:+UseParallelOldGC

-Xms40m
-Xmx40m
-Xmn16m
-XX:+UseParallelOldGC
-XX:SurvivorRatio=6
-verbose:gc 
-XX:+PrintGC
-XX:+PrintGCDetails
输出:
minor gc should happen
[GC [PSYoungGen: 11509K->1200K(14336K)] 11509K->1200K(38912K), 0.0029191 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
...
说明使用-XX:+UseParallelOldGC时,Minor GC使用的是并行回收GC -XX:+UseParallelGC

5. 单独使用 -XX:+UseConcMarkSweepGC(Major GC方式)
-Xms40m
-Xmx40m
-Xmn16m
-XX:+UseConcMarkSweepGC
-XX:SurvivorRatio=6
-verbose:gc 
-XX:+PrintGC
-XX:+PrintGCDetails
输出为:
minor gc should happen
[GC [DefNew: 11509K->1173K(14336K), 0.0046844 secs] 11509K->1173K(38912K), 0.0047808 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
...
说明 Minor GC使用的是串行GC,-XX:+UseSerialGC,即,单独配置-XX:+UseConcMarkSweepGC时,
默认-XX:+UseConcMarkSweepGC和-XX:+UseSerialGC配合使用

-XX:+UseConcMarkSweepGC -XX:+UseParNewGC 只有这种组合是合法的,也可以省略-XX:+UseParNewGC
下面组合都不行
-XX:+UseConcMarkSweepGC -XX:+UseParallelOldGC
-XX:+UseConcMarkSweepGC -XX:+UseParallelGC
-XX:+UseConcMarkSweepGC -XX:+UseSerialGC

 */
public class MutilGCLog
{
  private static void happenMinorGC(int happenMinorGCIndex) throws Exception
  {
    for(int i=0;i<happenMinorGCIndex;i++)
    {
      if(i==happenMinorGCIndex - 1)
      {
        Thread.sleep(2000);
        System.out.println("minor gc should happen");
        new MemoryObject(1024 * 1024 * 3);
      }
      new MemoryObject(1024 * 1024);
      //Thread.sleep(5000);
    }
  }
  
  public static void main(String[] args) throws Exception
  {
    MemoryObject object = new MemoryObject(1024 * 1024);
    happenMinorGC(11);
    Thread.sleep(2000);
  }
}

 

 

 

 

 

0
1
分享到:
评论

相关推荐

    JVM_GC_-调优总结.pdf

    JVM_GC_-调优总结

    Sun Hotspot V1.6.0 JVM GC PPT.pdf

    jvm 结构介绍、GC相关知识总结

    JVM、GC详解及调优.pdf

    本文档详细讲解了JVM(Java Visual Mathine)的方方面面,首先由java的特性来描绘JVM的大致应用,再详细阐释了 JVM 的原理及内存管理机制和调优,讲述了与JVM密切相关的 Java GC 机制,最后对 JVM 调优进行了总结。...

    深入虚拟机---JVM调优总结(摘自网上网上大牛分享).pdf

    深入虚拟机---JVM调优总结(摘自网上网上大牛分享),主要是详细介绍了gc的收集,觉得不错。

    JVM——总结思维导图

    JVM——总结思维导图

    JVM体系结构与GC调优总结

    JVM体系结构与GC调优总结,很详尽,面试必备呀,值得拥有!

    深入java虚拟机

    1.1 JVM调优总结(一)-一些概念 1.2 JVM调优总结(二)-一些概念 1.3 JVM调优总结(三)-基本垃圾回收算法 1.4 JVM调优总结(四)-垃圾回收面临的问题 1.5 JVM调优总结(五)-分代垃圾回收详述1 1.6 JVM调优总结...

    JVM GC问题和垃圾回收器讲解.pdf

    有关JVM垃圾回收器讲解,详细讲解了10种垃圾回收器的详细知识点,是自己面试时候自己进行总结的,费劲了心血,感谢各位的下载支持

    JVM调优文档,自己总结汇总关于GC和性能的文章

    JVM,性能,调优,GC JVM调优文档,自己总结汇总关于GC和性能的文章

    对JVM调优的总结经验.docx

    JVM调优总结

    个人总结JVM脑图

    详解JVM组成,GC,内存区域,以及一些GC机制和算法,一些简单的调优

    JDK9GC-cheatsheet.pdf

    今天我们讲讲JDK9中的JVM GC调优参数,JDK9中JVM的参数总共有2142个,其中正式的参数有659个。好像比JDK8中的参数要少一点。 为了方便大家的参考,特意将JDK9中的GC参数总结成了一张PDF,这个PDF比之前总结的JDK8的...

    jvm相关总结

    jvm的相关概念,运行机制,参数配置,gc算法和种类,监控工具,等等

    JVM的调优总结----------

    JVM的调优总结 1.JVM配置 2.GC算法

    Jvm内存面试问题总结(2020).docx

    自己在学习和面试过程中总结的一些常见面试题 , 包含了java内存模型 , java8以后内存变化. 垃圾回收算法, 常见的垃圾回收器 , G1垃圾回收器的优化 堆外内存如何使用等. 希望和大家共同进步 . 祝拿到满意的...

    JVM深入理解.xmind

    文件总结了JVM的体系结构:四大块,类装载子系统(class loader subsystem),执行引擎子系统(Executionengine子系统),垃圾回收系统(gc),运行时数据区(JVM内存)。

    深入JVM内核—原理、诊断与优化

    1、初始化JVM 2、JVM运行机制 3、常用JVM配置参数 4、算法和种类 5、GC参数 6、类 7、性能监控 8、jvm堆分析 9、锁 10、class文件结构 11、字节码执行 12、总结

    JVM参数设置详细说明

    后来我们就用CMS gc(-XX:+UseConcMarkSweepGC),当时的总heap还是3g,新生代1.5g后,观察不是很理想,改为jvm heap为2g新生代设置-Xmn1g,在这样的情况下young gc发生的频率变成7、8秒一次,平均每次时间40-50毫秒...

    GC.mmap-垃圾回收算法脑图

    GC总结

    GC知识框架.png

    这是有关GC知识点完整版的思维导图,可以在我的博客中查看详细总结:https://blog.csdn.net/weixin_34566605/article/details/104784905

Global site tag (gtag.js) - Google Analytics