网上看到一道题,“写一段程序,让其运行时的表现为触发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