写一段程序,让其运行时的表现为触发5次ygc,而后3次fgc,而后3次ygc,而后1次fgc,请给出代码以及启动参数(附说明)

网上看到一道题,“写一段程序,让其运行时的表现为触发5次ygc,而后3次fgc,而后3次ygc,而后1次fgc,请给出代码以及启动参数。”,这种题对于我这种假程序猿太难了,练练手吧!这对于jvm的GC机制是有好处的。硬着头皮试下,理解下。万一有错,明眼人指出下。java

编写以下(参考网上示例):(这里也经过JAVA相关类,读取打印了JVM的初始化堆、内存信息)web

package com.chl.jvm;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;

/**
 * 需求:写一段程序,让其运行时的表现为触发5次ygc,而后3次fgc,而后3次ygc,而后1次fgc,请给出代码以及启动参数。
 * VM设置:-Xms41m -Xmx41m -Xmn10m -XX:+UseParallelGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
 * -Xms41m 				堆最小值
 * -Xmx41m 				堆最大值
 * -Xmn10m 				新生代大小大小(推荐 3/8)
 * -XX:+UseParallelGC   使用并行收集器
 * @author chenhailong
 *
 *  初始化时:835k(堆内存)
 * 第一次add:3907k
 * 第二次add:6979k
 * 第三次add: eden + survivor1 = 9216k < 6979k + 3072k,区空间不够,开始 YGC
 * YGC  6979k -> 416k(9216k) 表示年轻代 GC前为6979,GC后426k.年轻代总大小9216k
 */
public class GCtest {
	
	/**
	 * 最小的单位
	 */
	private static final int UNIT_MB = 1024 * 1024;

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void main(String[] args) {
		getJvmInfo();
		int count = 1;
        List caches = new ArrayList();
        System.out.println("--初始化时已用堆值:" +  ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()/1024+"k");
        for (int i = 1; i <= 12; i++){
        	if(i==11) {
        		System.out.println("--caches准备添加第11次,old区内存不够,开始full GC 前先执行minor GC 第"+5+"次,FGC 第1次(触发条件:【MinorGC后存活的对象超过了老年代剩余空间】)");
        	}
            caches.add(new byte[3 * UNIT_MB]);
            if(i%2==0 && i!=10) {
            	System.out.println("--caches添加第"+i+"次后,eden + survivor 的内存不够,开始minor GC 第"+count+"次");
            	count++;
            }else {
            	System.out.println("--caches添加第"+i+"次");
            }
        }
        System.out.println("目前整个堆内存已经36m多,Young区6M多,Old区最大值为32M");
        caches.remove(0);//释放空间,从新添加 ,若是不释放空间,会报错:java.lang.OutOfMemoryError: Java heap space 【这里这样作,主要为了防止数组对象实际大小超过堆大小】
        System.out.println("--FGC开始 第2次(触发条件:晋升到老年代的大小超过了老年代剩余大小)");
        caches.add(new byte[3 * UNIT_MB]);
        System.out.println("本次FGC,移植了Young区的一部分到Old区,致使Young区还有3M左右");
        for (int i = 0; i < 8; i++){//这里是为了下次FGC后,直接减小老年代的内存大小,从而正常YGC
            caches.remove(0);
        }
        System.out.println("--FGC开始 第3次(触发条件:同上)");
        caches.add(new byte[3 * UNIT_MB]);
        
        for (int i = 0; i < 6; i++){
            caches.add(new byte[3 * UNIT_MB]);
        }
	}

	/**
	 * 经过代码打印程序的堆、内存信息
	 */
	public static void getJvmInfo() {
		System.out.println("-----------------------JVM-Info-start----------------");
		
		MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
		MemoryUsage mu = memoryMXBean.getHeapMemoryUsage();
		
		System.out.println("heapInfo:" +  mu);
		System.out.println("初始化堆:" +  mu.getInit()/1024/1024 + "Mb");
        System.out.println("最大堆值:"  +  mu.getMax()/1024/1024 + "Mb");
        System.out.println("已用堆值:" +  mu.getUsed()/1024/1024 + "Mb");
        
        MemoryUsage none = memoryMXBean.getNonHeapMemoryUsage();
        System.out.println("non-heap Info(非堆内存):" +  none);
        
        
        List<String> args = ManagementFactory.getRuntimeMXBean().getInputArguments();
        System.out.println("运行时VM参数:"+args);
        
        System.out.println("运行时总内存"+Runtime.getRuntime().totalMemory()/1024/1024);
        System.out.println("运行时空闲内存"+Runtime.getRuntime().freeMemory()/1024/1024);
        System.out.println("运行时最大内存"+Runtime.getRuntime().maxMemory()/1024/1024);
        
		System.out.println("-----------------------JVM-Info-end----------------");
		System.out.println("--");
		System.out.println("--");
		System.out.println("--");
	}
}
-----------------------JVM-Info-start----------------
heapInfo:init = 44040192(43008K) used = 855568(835K) committed = 42991616(41984K) max = 42991616(41984K)
初始化堆:42Mb
最大堆值:41Mb
已用堆值:0Mb
non-heap Info(非堆内存):init = 2555904(2496K) used = 4240760(4141K) committed = 8060928(7872K) max = -1(-1K)
运行时VM参数:[-Xms41m, -Xmx41m, -Xmn10m, -XX:+UseParallelGC, -XX:+PrintGCDetails, -XX:+PrintGCTimeStamps, -Dfile.encoding=UTF-8]
运行时总内存41
运行时空闲内存40
运行时最大内存41
-----------------------JVM-Info-end----------------
--
--
--
--初始化时已用堆值:835k
--caches添加第1次
--caches添加第2次后,eden + survivor 的内存不够,开始minor GC 第1次
0.089: [GC (Allocation Failure) [PSYoungGen: 6979K->432K(9216K)] 6979K->6584K(41984K), 0.0046451 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
--caches添加第3次
--caches添加第4次后,eden + survivor 的内存不够,开始minor GC 第2次
0.094: [GC (Allocation Failure) [PSYoungGen: 6736K->400K(9216K)] 12888K->12696K(41984K), 0.0067987 secs] [Times: user=0.01 sys=0.01, real=0.00 secs] 
--caches添加第5次
--caches添加第6次后,eden + survivor 的内存不够,开始minor GC 第3次
0.102: [GC (Allocation Failure) [PSYoungGen: 6868K->384K(9216K)] 19164K->18824K(41984K), 0.0044920 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
--caches添加第7次
--caches添加第8次后,eden + survivor 的内存不够,开始minor GC 第4次
0.107: [GC (Allocation Failure) [PSYoungGen: 6687K->384K(9216K)] 25127K->24968K(41984K), 0.0046478 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
--caches添加第9次
--caches添加第10次
--caches准备添加第11次,old区内存不够,开始full GC 前先执行minor GC 第5次,FGC 第1次(触发条件:【MinorGC后存活的对象超过了老年代剩余空间】)
0.112: [GC (Allocation Failure) [PSYoungGen: 6687K->416K(9216K)] 31271K->31144K(41984K), 0.0037305 secs] [Times: user=0.00 sys=0.01, real=0.01 secs] 
0.116: [Full GC (Ergonomics) [PSYoungGen: 416K->0K(9216K)] [ParOldGen: 30728K->31032K(32768K)] 31144K->31032K(41984K), [Metaspace: 2764K->2764K(1056768K)], 0.0064116 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
--caches添加第11次
--caches添加第12次后,eden + survivor 的内存不够,开始minor GC 第5次
目前整个堆内存已经36m多,Young区6M多,Old区最大值为32M
--FGC开始 第2次(触发条件:晋升到老年代的大小超过了老年代剩余大小)
0.124: [Full GC (Ergonomics) [PSYoungGen: 6303K->3072K(9216K)] [ParOldGen: 31032K->31032K(32768K)] 37336K->34105K(41984K), [Metaspace: 2765K->2765K(1056768K)], 0.0054599 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
本次FGC,移植了Young区的一部分到Old区,致使Young区还有3M左右
--FGC开始 第3次(触发条件:同上)
0.130: [Full GC (Ergonomics) [PSYoungGen: 6303K->0K(9216K)] [ParOldGen: 31032K->12601K(32768K)] 37336K->12601K(41984K), [Metaspace: 2765K->2765K(1056768K)], 0.0044791 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
0.135: [GC (Allocation Failure) [PSYoungGen: 6275K->0K(8704K)] 18876K->18745K(41472K), 0.0010285 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
0.137: [GC (Allocation Failure) [PSYoungGen: 6257K->0K(9216K)] 25002K->24889K(41984K), 0.0009595 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
0.138: [GC (Allocation Failure) [PSYoungGen: 6274K->0K(9216K)] 31163K->31033K(41984K), 0.0015084 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
0.140: [Full GC (Ergonomics) [PSYoungGen: 0K->0K(9216K)] [ParOldGen: 31033K->31033K(32768K)] 31033K->31033K(41984K), [Metaspace: 2765K->2765K(1056768K)], 0.0023516 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 9216K, used 3236K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 8192K, 39% used [0x00000007bf600000,0x00000007bf9290e0,0x00000007bfe00000)
  from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
  to   space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
 ParOldGen       total 32768K, used 31033K [0x00000007bd600000, 0x00000007bf600000, 0x00000007bf600000)
  object space 32768K, 94% used [0x00000007bd600000,0x00000007bf44e4c0,0x00000007bf600000)
 Metaspace       used 2771K, capacity 4490K, committed 4864K, reserved 1056768K
  class space    used 299K, capacity 386K, committed 512K, reserved 1048576K