zoukankan      html  css  js  c++  java
  • JVM测试总结_基于Java8(自用)

    一、jvm垃圾回收器

    引用链接:https://www.cnblogs.com/chenpt/p/9803298.html

    jvm的垃圾回收器有serial收集器、parnew收集器、parallel scavenge收集器、serial old 收集器、parallel old收集器、cms收集器、g1收集器

    HotSpot虚拟机所包含的收集器:

    图中展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,则说明它们可以搭配使用。虚拟机所处的区域则表示它是属于新生代还是老年代收集器。

    新生代收集器:Serial、ParNew、Parallel Scavenge

    老年代收集器:CMS、Serial Old、Parallel Old

    整堆收集器: G1

    二、jvm内存分配担保机制

    引用链接:https://mp.weixin.qq.com/s?__biz=MzA5MzQ2NTY0OA==&mid=2650797224&idx=1&sn=5819bd097e6dabab34db382be2d0182c&chksm=885629f7bf21a0e1fe382626f8d272ee9c4066109f329ef93a205c29e37e9376f455c1710903&scene=21#wechat_redirect

    1、指定Serial+Serial Old作为jvm垃圾回收器

    jvm启动参数如下:

    -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC

    其中10M分配给新生代,另外10M分配给老生代。新生代中eden和survivor区的比例为8:1,eden区所分配内存为8M,两个survivor区分别为1M,新生代总可用空间为9M。

    测试代码如下:

    package handlepromotion;
    
    public class HandlePromotionFailure {
        private static final int _1MB = 1024 * 1024;
        
        public static void testHandlePromotionFailure() {
            byte[] allocation1 = new byte[2* _1MB];
            byte[] allocation2 = new byte[2* _1MB];
            byte[] allocation3 = new byte[2* _1MB];
            byte[] allocation4 = new byte[4* _1MB];
        }
        
        public static void main(String[] args) {
            testHandlePromotionFailure();
        }
        
    }

    测试结果:

    [GC (Allocation Failure) [DefNew: 7127K->526K(9216K), 0.0062127 secs] 7127K->6670K(19456K), 0.0062962 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
    Heap
    def new generation total 9216K, used 4704K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
    eden space 8192K, 51% used [0x00000000fec00000, 0x00000000ff014930, 0x00000000ff400000)
    from space 1024K, 51% used [0x00000000ff500000, 0x00000000ff583918, 0x00000000ff600000)
    to space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
    tenured generation total 10240K, used 6144K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
    the space 10240K, 60% used [0x00000000ff600000, 0x00000000ffc00030, 0x00000000ffc00200, 0x0000000100000000)
    Metaspace used 2671K, capacity 4486K, committed 4864K, reserved 1056768K
    class space used 288K, capacity 386K, committed 512K, reserved 1048576K

    测试分析:

    eden区依次创建了三个2M的对象,占用内存6M,新生代总可用空间为9M,eden区可用空间为8M,由于9M-6M=3M<4M,从而进行GC,发现survivor区空间不足。此时,JVM就启动了内存分配的担保机制,把这6MB的三个对象直接转移到了老年代。此时就把新生代的空间腾出来了,然后把第四个对象(4MB)放入了eden区中。

    2、指定Parallel Scavenge+Serial Old作为jvm垃圾回收器

    jvm参数将-XX:+UseSerialGC修改为-XX:+UseParallelGC

    测试代码如下:

    package handlepromotion;
    
    public class HandlePromotionFailure {
        private static final int _1MB = 1024 * 1024;
        
        public static void testHandlePromotionFailure() {
            byte[] allocation1 = new byte[2* _1MB];
            byte[] allocation2 = new byte[2* _1MB];
            byte[] allocation3 = new byte[2* _1MB];
            byte[] allocation4 = new byte[4* _1MB];
        }
        
        public static void main(String[] args) {
            testHandlePromotionFailure();
        }
        
    }

    测试结果:

    Heap
    PSYoungGen total 9216K, used 7292K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
    eden space 8192K, 89% used [0x00000000ff600000,0x00000000ffd1f050,0x00000000ffe00000)
    from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
    to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
    ParOldGen total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
    object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000010,0x00000000ff600000)
    Metaspace used 2670K, capacity 4486K, committed 4864K, reserved 1056768K
    class space used 288K, capacity 386K, committed 512K, reserved 1048576K

    接下来我们将第四个对象由4M改为3M,测试结果如下:

    [GC (Allocation Failure) [PSYoungGen: 7127K->632K(9216K)] 7127K->6784K(19456K), 0.0053005 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 632K->0K(9216K)] [ParOldGen: 6152K->6669K(10240K)] 6784K->6669K(19456K), [Metaspace: 2664K->2664K(1056768K)], 0.0082392 secs] [Times: user=0.05 sys=0.00, real=0.01 secs] 
    Heap
     PSYoungGen      total 9216K, used 3154K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
      eden space 8192K, 38% used [0x00000000ff600000,0x00000000ff914930,0x00000000ffe00000)
      from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
      to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
     ParOldGen       total 10240K, used 6669K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
      object space 10240K, 65% used [0x00000000fec00000,0x00000000ff283538,0x00000000ff600000)
     Metaspace       used 2671K, capacity 4486K, committed 4864K, reserved 1056768K
      class space    used 288K, capacity 386K, committed 512K, reserved 1048576K

    测试分析:

    通过和上面的测试结果对比,我们发现当第四个对象无法放入eden区时,此时不会直接进行GC,而是判断如果要分配的内存>=eden区的一半,那么会直接把要分配的内存放入老年代中。否则进行GC操作,如果survivor区空间不足,则把eden区中的6M的对象直接放入老年代区中,eden区新创建4M的对象。

    那么为什么3M的时候出现了FullGC呢,原作者也给出了他的答案(https://cloud.tencent.com/developer/article/1082687)。

    大概的意思是这种情况下偶尔会发生FullGC,至于原因大概是在使用Parallel Scavenge收集器时,jvm会进行预测,如果晋升到老年代的平均大小大于老年代剩余大小,则认为需要一次FullGC。当虚拟机估算出下次分配可能会发生无法分配的问题时,则会提前发生一次FullGC。

    那么针对上面的例子,当gc操作把eden区的6M全部晋升到老年代区中,此时老年代区的大小为10M-6M=4M,jvm预测下一次晋升时老年代空间可能不足,于是提前进行了一次FullGC。

    简单验证下,修改jvm参数为-Xms24M -Xmx24M -Xmn10M,将heap内存加大,新生代不变,此时老年代大小为14M。

    此时测试结果如下,未发生FullGC:

    [GC (Allocation Failure) [PSYoungGen: 7127K->632K(9216K)] 7127K->6784K(23552K), 0.0043651 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    Heap
     PSYoungGen      total 9216K, used 3786K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
      eden space 8192K, 38% used [0x00000000ff600000,0x00000000ff914930,0x00000000ffe00000)
      from space 1024K, 61% used [0x00000000ffe00000,0x00000000ffe9e030,0x00000000fff00000)
      to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
     ParOldGen       total 14336K, used 6152K [0x00000000fe800000, 0x00000000ff600000, 0x00000000ff600000)
      object space 14336K, 42% used [0x00000000fe800000,0x00000000fee02030,0x00000000ff600000)
     Metaspace       used 2671K, capacity 4486K, committed 4864K, reserved 1056768K
      class space    used 288K, capacity 386K, committed 512K, reserved 1048576K
  • 相关阅读:
    判断输入的年份是闰年还是平年!!!
    键盘接收数,接收运算符号进行运算!!
    eclipse项目上如何传到码云上!新手,简单易懂,希望对你有所帮助。
    jquery dialog弹出框简单写法和一些属性的应用,写的不好,大佬勿喷!谢谢!
    新手冒泡排序,随机生成十个数。
    新手java九九乘法表
    Lambda表达式
    如何删除gitee仓库的文件
    Collection方法
    java冒泡排序的几种写法
  • 原文地址:https://www.cnblogs.com/java-meng/p/11096985.html
Copyright © 2011-2022 走看看