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

触发特定GC序列
本文介绍了一个Java程序,通过特定的内存分配策略,成功触发了5次YGC,然后3次FGC,接着3次YGC,最后1次FGC的垃圾回收序列。通过调整堆大小和使用并行收集器,演示了不同条件下GC触发的机制。

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

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

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值