新生代与老年代垃圾收集器实现详解

在上一节【https://www.cnblogs.com/webor2006/p/10989175.html】中已经开启GC的第一次实践,这次继续其于上一次的例子进行扩展来阐述一些其它的知识,先回顾一下上一节的代码:

其中GC参数我们配置如下:

其中对于试验代码中为啥要选用字节数组来实验其实是有原因的,因为如果用int的话它占用4个字节还存在换算的因素存在,而byte则就占一个字节,所以用它比较好理解,接着基于它来继续修改程序:

再运行:

/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/bin/java -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/lib/tools.jar:/Users/xiongwei/Documents/workspace/IntelliJSpace/jvm_lectue/out/production/classes:/Users/xiongwei/.gradle/caches/modules-2/files-2.1/mysql/mysql-connector-java/5.1.34/46deba4adbdb4967367b013cbc67b7f7373da60a/mysql-connector-java-5.1.34.jar:/Users/xiongwei/.gradle/caches/modules-2/files-2.1/cglib/cglib/3.2.0/bced5c83ed985c080a24dc5a42b0ca631556f413/cglib-3.2.0.jar:/Users/xiongwei/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.0.3/dcc2193db20e19e1feca8b1240dbbc4e190824fa/asm-5.0.3.jar:/Users/xiongwei/.gradle/caches/modules-2/files-2.1/org.apache.ant/ant/1.9.4/6d473e8653d952045f550f4ef225a9591b79094a/ant-1.9.4.jar:/Users/xiongwei/.gradle/caches/modules-2/files-2.1/org.apache.ant/ant-launcher/1.9.4/334b62cb4be0432769679e8b94e83f8fd5ed395c/ant-launcher-1.9.4.jar com.jvm.gc.MyTest1
[GC (Allocation Failure) [PSYoungGen: 7167K->432K(9216K)] 7167K->6576K(19456K), 0.0060992 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 432K->0K(9216K)] [ParOldGen: 6144K->6487K(10240K)] 6576K->6487K(19456K), [Metaspace: 2649K->2649K(1056768K)], 0.0049758 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
hello world
Heap
 PSYoungGen      total 9216K, used 2290K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 8192K, 27% used [0x00000007bf600000,0x00000007bf83c9a0,0x00000007bfe00000)
  from space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
  to   space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
 ParOldGen       total 10240K, used 6487K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  object space 10240K, 63% used [0x00000007bec00000,0x00000007bf255d40,0x00000007bf600000)
 Metaspace       used 2656K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 287K, capacity 386K, committed 512K, reserved 1048576K

Process finished with exit code 0

其中多出了一个Full GC,下面对它的日志进行一下解读:

那这单词啥意思呢?

啥意思。。不懂,反正就是其中发生Full GC的一个原因呗,其中要特别注意的是:它产生的直接后果就是会出现Stop The World,简单STW这种情况,也就是业务线程会暂停一段时间,等它完成GC之后业务线程才会继续的恢复执行,所以,在日常的JVM的调优中应该尽最大努力避免出现Full GC的情况,因为它会导致新生代、老年代、元空间都会进行垃圾回收,下面继续看日志:

接下来再来看一个神奇的现象,我们将字节扩大再来看运行效果:

为什么???其实这里有一个理论可以解释:“如果在新生代中已经无法容纳下一个新创建的对象的话,该新对象会直接在老年代来诞生”,那结合目前咱们程序来解释,由于我们的新生代设置的总大小为10M:

而新生代由三个区域组成,如:

所以此时Eden空间应该是8M,而我们前三个字节已经申请了7M空间了:

当我们再新建一个4M的空间时,很显然该对象不能在Eden空间存放了,所以此时会将该4M的对象直接放到老年代里面来存放,所以在老年代中我们可以看到已用空间就刚好是4M多,如下:

最后再来介绍新生代和老年代使用的垃圾器的使用情况:

它表示:Parallel Scavenge (新生代垃圾收集器),其实上节【https://www.cnblogs.com/webor2006/p/10989175.html】也已经说明过,再来回顾一下当时的理论:

它表示:Parallel Old(老年代垃圾收集器),也同样回顾一下当时的理论说明【https://www.cnblogs.com/webor2006/p/10982448.html】:

也就是说JDK中新生代和老年代默认的垃圾回收器为以上两种,当然不同的JDK可能默认的垃圾收集器不太一样,我目前使用的JDK版本为:

原文地址:https://www.cnblogs.com/webor2006/p/10990736.html