JVM学习笔记——垃圾回收篇( 四 )


// 相关配置信息:配置默认大?。?设置回收方法 , 显示GC详情,开启FullGC前进行gc// -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc -XX:-ScavengeBeforeFullGC/*首先我们展示不添加内存的状况*/package cn.itcast.jvm.t2;import java.util.ArrayList;public class Demo2_1 {private static final int _512KB = 512 * 1024;private static final int _1MB = 1024 * 1024;private static final int _6MB = 6 * 1024 * 1024;private static final int _7MB = 7 * 1024 * 1024;private static final int _8MB = 8 * 1024 * 1024;public static void main(String[] args) throws InterruptedException {new Thread(() -> {ArrayList<byte[]> list = new ArrayList<>();}).start();System.out.println("sleep....");Thread.sleep(1000L);}}/*其中def new generation,eden space是新生代,tenured generation是老年代,from,to幸存区Heap def new generationtotal 9216K, used 4510K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)eden space 8192K,55% used [0x00000000fec00000, 0x00000000ff067aa0, 0x00000000ff400000)from space 1024K,0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)tospace 1024K,0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000) tenured generationtotal 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)the space 10240K,0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000) Metaspaceused 4362K, capacity 4714K, committed 4992K, reserved 1056768Kclass spaceused 480K, capacity 533K, committed 640K, reserved 1048576K*//*然后我们展示添加1mb的情况*/package cn.itcast.jvm.t2;import java.util.ArrayList;public class Demo2_1 {private static final int _512KB = 512 * 1024;private static final int _1MB = 1024 * 1024;private static final int _6MB = 6 * 1024 * 1024;private static final int _7MB = 7 * 1024 * 1024;private static final int _8MB = 8 * 1024 * 1024;public static void main(String[] args) throws InterruptedException {new Thread(() -> {ArrayList<byte[]> list = new ArrayList<>();list.add(new byte[_1MB]);}).start();System.out.println("sleep....");Thread.sleep(1000L);}}/*我们可以发现新生代数据增加,老年代未发生变化Heap def new generationtotal 9216K, used 5534K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)eden space 8192K,67% used [0x00000000fec00000, 0x00000000ff167a40, 0x00000000ff400000)from space 1024K,0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)tospace 1024K,0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000) tenured generationtotal 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)the space 10240K,0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000) Metaspaceused 4354K, capacity 4714K, committed 4992K, reserved 1056768Kclass spaceused 480K, capacity 533K, committed 640K, reserved 1048576*//*最后需要补充讲解一点:当我们的新生代不足以装载数据内存时,我们会直接将其装入老年代(老年代能够装载情况下)*/package cn.itcast.jvm.t2;import java.util.ArrayList;public class Demo2_1 {private static final int _512KB = 512 * 1024;private static final int _1MB = 1024 * 1024;private static final int _6MB = 6 * 1024 * 1024;private static final int _7MB = 7 * 1024 * 1024;private static final int _8MB = 8 * 1024 * 1024;public static void main(String[] args) throws InterruptedException {new Thread(() -> {ArrayList<byte[]> list = new ArrayList<>();list.add(new byte[_8MB]);}).start();System.out.println("sleep....");Thread.sleep(1000L);}}/*我们会发现eden的值未发生变化 , 但是tenured generation里面装载了8192KHeap def new generationtotal 9216K, used 4510K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)eden space 8192K,55% used [0x00000000fec00000, 0x00000000ff067a30, 0x00000000ff400000)from space 1024K,0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)tospace 1024K,0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000) tenured generationtotal 10240K, used 8192K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)the space 10240K,80% used [0x00000000ff600000, 0x00000000ffe00010, 0x00000000ffe00200, 0x0000000100000000) Metaspaceused 4360K, capacity 4714K, committed 4992K, reserved 1056768Kclass spaceused 480K, capacity 533K, committed 640K, reserved 1048576K*//*当然,当我们的新生代和老年代都不足以装载时 , 系统报错~*/package cn.itcast.jvm.t2;import java.util.ArrayList;public class Demo2_1 {private static final int _512KB = 512 * 1024;private static final int _1MB = 1024 * 1024;private static final int _6MB = 6 * 1024 * 1024;private static final int _7MB = 7 * 1024 * 1024;private static final int _8MB = 8 * 1024 * 1024;public static void main(String[] args) throws InterruptedException {new Thread(() -> {ArrayList<byte[]> list = new ArrayList<>();list.add(new byte[_8MB]);list.add(new byte[_8MB]);}).start();System.out.println("sleep....");Thread.sleep(1000L);}}/*我们首先会看到他在Full gc之前做了一次小gc,然后做了一次Full gc,可是这并无法解决问题[GC (Allocation Failure) [DefNew: 4345K->999K(9216K), 0.0016573 secs][Tenured: 8192K->9189K(10240K), 0.0022899 secs] 12537K->9189K(19456K), [Metaspace: 4352K->4352K(1056768K)], 0.0039931 secs] [Times: user=0.00 sys=0.00, real=0.00 secs][Full GC (Allocation Failure) [Tenured: 9189K->9124K(10240K), 0.0018331 secs] 9189K->9124K(19456K), [Metaspace: 4352K->4352K(1056768K)], 0.0018528 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 然后系统进行报错Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space at cn.itcast.jvm.t2.Demo2_1.lambda$main$0(Demo2_1.java:20) at cn.itcast.jvm.t2.Demo2_1$$Lambda$1/1023892928.run(Unknown Source) at java.lang.Thread.run(Thread.java:750)最后我们可以看到老年代占用了89%,第一个数据仍旧保存,但第二个数据无法保存导致报错Heap def new generationtotal 9216K, used 366K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)eden space 8192K,4% used [0x00000000fec00000, 0x00000000fec5baa8, 0x00000000ff400000)from space 1024K,0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)tospace 1024K,0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000) tenured generationtotal 10240K, used 9124K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)the space 10240K,89% used [0x00000000ff600000, 0x00000000ffee93c0, 0x00000000ffee9400, 0x0000000100000000) Metaspaceused 4379K, capacity 4704K, committed 4992K, reserved 1056768Kclass spaceused 480K, capacity 528K, committed 640K, reserved 1048576K我们还需要注意的是:即使内存不足发生报错,但该程序不会结束;系统只会释放自己当前项目的进程而不会影响其他进程*/

推荐阅读