zoukankan      html  css  js  c++  java
  • 垃圾回收日志与算法深度解读

    经过前面对于JVM垃圾回收学习了纯理论相关的东东,这次则要开始用代码编写大量的实验来对理论进行佐证,下面开始,先在IntelliJ IDEA工程中新建一个全新的包:

    然后新建一个类:

    接下来则会编写一个超级简单的程序,程序虽简单,但是通过增加一些JVM的参数可以用简单的程序来阐述JVM垃圾回收的很多知识点,所以意义还是挺大的,具体如下:

    哇,确实是简单,但是这里有个注意点:就是对于这个byte类型的数组其实里面存放的是为0的原生类型,可以打印看一下:

    而如果是引用类型的数组则里面每个存放的是null,需要明白,接下来多创建几个byte数组:

    目前来看这是一个非常非常之low的程序,但是如果咱们给JVM增加一些运行参数,再输出看到的东东则会大不一样,下面来增加一些启动参数:

    这里有意将堆空间设置得较小以便可以供咱们观察GC的情况,继续:

    还有最后一个参数:

    这代表啥意思呢?其实它代表新生代的比例,如之前理论所介绍:

    也就是这里的配置就代表新生代的区域是8:1:1,也就是Eden空间和Survivor空间的占比是8:1。接下来咱们再来运行一下:

    而这些信息的输出其实是JVM的这个参数发挥着作用,如下:

    不信咱们将这个参数去掉再来运行:

    果真就木有了,所以还是将该参数加回来。其实目前没有GC相关的日志出来,接下来再来创建一个新的字节数组:

    再运行:

    /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->464K(9216K)] 7167K->6616K(19456K), 0.0060472 secs] [Times: user=0.01 sys=0.01, real=0.01 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 464K->0K(9216K)] [ParOldGen: 6152K->6487K(10240K)] 6616K->6487K(19456K), [Metaspace: 2649K->2649K(1056768K)], 0.0048810 secs] [Times: user=0.01 sys=0.00, real=0.00 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

    此时就出现了两种类型的GC,说明发生了GC操作,而这两种类型的GC其实在之前的理论学习中也提及过,回顾一下:

    接下来咱们再来修改程序:

    也就是说随着我们创建的字节的多少,其GC的输出也会不一样,接下来则对这些日志输出进行一个解答,了解它们能够更加深刻的理论GC相关的东东:

    其实图中的疑问也来自于之前的理论学习,回顾下:

    也就是说对于咱们的新生代是采用PS收集器来进行垃圾回收的,接着继续往下分析:

    但是!!我在配置的JVM参数新生代的容量其实设置的是10M,如下:

    为啥我们在日志中看到的新生代总的容量只有9M呢?这里就还得回到新生代的空间组成了,它是由一个Eden空间和两个Survivor空间组成的,其中Survivor只会用一个,另一个会是空间进行数据交换用的,所以其总的新生代的大小就是Eden空间(8M)+1个Survivor空间(1M) = 9M。继续往下分析日志:

    为啥总的堆大小的容量是19M,而非我们指定的20M呢?

    还是因为年轻代总大小会少1M。往下继续:

    至此对于GC的日志就彻底了解了,对于FULL GC其实里面的含义也一样,接下来则是整个垃圾回收的汇总信息,分析一下:

    最后咱们来计算一下这个老年代已使用了8K是如何得出来的?

    还得由之前的GC日志来得算,下面来算一下:

    这俩一相减就得出在新生代进行了gc之后所释放的容量为8191-464=7727,接着再来看一下总堆的释放情况:

    那有个疑问:为啥总的堆空间释放的大小还不如新生代释放的大小呢?这里需要注意:对于新生代的释放其实分为两种:一是真正的被回收的,二是没有真正被回收,而是该对象进升到老年代了,而堆空间的释放值代表是真正被释放的大小。

    那这俩数据之间有啥关系呢?其实这个关系是非常微妙的,为啥,看一下:“7727-7719=8k”,这不就是我们看到老年代已使用的大小么?

    所以新生代释放的大小-总堆释放的大小则就是从新生代进升到老年代的容量大小。

  • 相关阅读:
    Tomcat搭建Web 应用服务器
    前端代码的开发标准和规范
    全局关键字搜索:Element UI Table内容过滤jQuery过滤器fastLiveFilter插件BootstrapVue插件;
    Highchartsjs使用总结及实时动态刷新图
    百度统计微信网站绑定(vue项目)
    对Vuejs框架原理名词解读
    xml
    webservice
    类加载器
    引入spring时 XML文档中的xmlns、xmlns:xsi和xsi:schemaLocation
  • 原文地址:https://www.cnblogs.com/webor2006/p/10989175.html
Copyright © 2011-2022 走看看