玩转Java虚拟机(十一)

打卡学习JVM,第十一天

本人学习过程中所整理的代码,源码地址

垃圾回收日志

-verbose:gc&-XX:+PrintGCDetails**

测试用例JVM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

public class MyTest1 {
    public static void main(String[] args) {
        int size = 1024 * 1024;
        byte[] myAlloc2 = new byte[2 * size];
        byte[] myAlloc3 = new byte[2 * size];
        byte[] myAlloc4 = new byte[3 * size];

        System.out.println("hello world");
    }
}

输出结果:

[GC (Allocation Failure) [PSYoungGen: 6322K->856K(9216K)] 6322K->4960K(19456K), 0.0030547 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
hello world
Heap
 PSYoungGen      total 9216K, used 4165K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 40% used [0x00000000ff600000,0x00000000ff93b650,0x00000000ffe00000)
  from space 1024K, 83% used [0x00000000ffe00000,0x00000000ffed6030,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 10240K, used 4104K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff002020,0x00000000ff600000)
 Metaspace       used 3448K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 376K, capacity 388K, committed 512K, reserved 1048576K

分析:

[GC (Allocation Failure) [PSYoungGen: 6322K->856K(9216K)] 6322K->4960K(19456K), 0.0030547 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

JDK1.8新生代、老年代默认垃圾收集器:
PSYoungGen:Parallel Scavenge(新生代垃圾收集器) ParOldGen:Parallel Old(老年代垃圾收集器)

  • 执行完GC后,新生代释放的空间容量:6322K - 856K = 5466K
  • 执行完GC后,总的堆空间释放的空间容量:6322K - 4960K = 1362K
  • 执行完GC后,新生代晋升到老年代的空间容量:5466K - 1362K = 4104K
ParOldGen       total 10240K, used 4104K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff002020,0x00000000ff600000)

可以使用jvisualvm监视程序运行期间的垃圾回收过程,从图中可以看出,当执行一次MInor GC时堆的使用量会下降
在这里插入图片描述

-XX:+UseSerialGC:更改为Serial垃圾收集器
-XX:PretenureSizeThreshold:设置对象超过多大时直接在老年代进行分配
-XX:MaxTenuringThreshold:在可以自动调节对象晋升到老年代阈值的GC中,设置该阈值的最大值,该参数的默认值为15,CMS中默认值为6,G1中默认为15(在JVM中,该数值是由4个bit来表示的,所以最大值是1111,即15)

经历了多次GC后,存活的对象会在From Survivor与To Survivor之间来回存放,而这里面的一个前提则是这两个空间有足够的大小来存放这些数据,在GC算法中,会计算每个对象年龄的大小,如果达到某个年龄后发现总大小已经大于了Survivor空间的50%,那么这时就需要调整阈值,不能再继续等到默认的15次GC后才能完成晋升,因为这样会导致Survivor空间不足,所以需要调整阈值,让这些存活对象尽快完成晋升。

测试用例:

JVM Option:-verbose:gc -Xmx200M -Xmn50M -XX:TargetSurvivorRatio=60 -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:MaxTenuringThreshold=3
public class MyTest4 {
    public static void main(String[] args) throws InterruptedException {
        byte[] byte1 = new byte[512 * 1024];
        byte[] byte2 = new byte[512 * 1024];

        myGc();
        Thread.sleep(1000);
        System.out.println("111111");

        myGc();
        Thread.sleep(1000);
        System.out.println("222222");

        myGc();
        Thread.sleep(1000);
        System.out.println("333333");

        myGc();
        Thread.sleep(1000);
        System.out.println("444444");

        byte[] byte3 = new byte[1024 * 1024];
        byte[] byte4 = new byte[1024 * 1024];
        byte[] byte5 = new byte[1024 * 1024];

        myGc();
        Thread.sleep(1000);
        System.out.println("555555");

        myGc();
        Thread.sleep(1000);
        System.out.println("666666");

        System.out.println("hello world");
    }
    private static void myGc() {
        for (int i = 0; i < 40; i++) {
            byte[] byteArray = new byte[1024 * 1024];
        }
    }
}

运行结果:

2020-03-23T20:52:00.724+0800: [GC (Allocation Failure) 2020-03-23T20:52:00.724+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
- age   1:    1733288 bytes,    1733288 total
: 40150K->1728K(46080K), 0.0017942 secs] 40150K->1728K(125952K), 0.0018953 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
111111
2020-03-23T20:52:01.735+0800: [GC (Allocation Failure) 2020-03-23T20:52:01.735+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
- age   1:     340672 bytes,     340672 total
- age   2:    1724184 bytes,    2064856 total
: 42459K->2169K(46080K), 0.0014859 secs] 42459K->2169K(125952K), 0.0015369 secs] [Times: user=0.08 sys=0.02, real=0.00 secs] 
222222
2020-03-23T20:52:02.742+0800: [GC (Allocation Failure) 2020-03-23T20:52:02.742+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
- age   1:         56 bytes,         56 total
- age   2:     340232 bytes,     340288 total
- age   3:    1780240 bytes,    2120528 total
: 42682K->2543K(46080K), 0.0013672 secs] 42682K->2543K(125952K), 0.0014284 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
333333
2020-03-23T20:52:03.751+0800: [GC (Allocation Failure) 2020-03-23T20:52:03.751+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
- age   1:         56 bytes,         56 total
- age   2:         56 bytes,        112 total
- age   3:     340152 bytes,     340264 total
: 43262K->952K(46080K), 0.0107885 secs] 43262K->2655K(125952K), 0.0109464 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
444444
2020-03-23T20:52:04.767+0800: [GC (Allocation Failure) 2020-03-23T20:52:04.768+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 1 (max 3)
- age   1:    3145832 bytes,    3145832 total
- age   2:         56 bytes,    3145888 total
- age   3:         56 bytes,    3145944 total
: 41678K->3152K(46080K), 0.0020806 secs] 43382K->5210K(125952K), 0.0021223 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
555555
2020-03-23T20:52:05.776+0800: [GC (Allocation Failure) 2020-03-23T20:52:05.776+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
- age   1:         56 bytes,         56 total
: 43883K->20K(46080K), 0.0052602 secs] 45942K->5150K(125952K), 0.0053688 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
666666
hello world
Heap
 par new generation   total 46080K, used 18021K [0x00000000f3800000, 0x00000000f6a00000, 0x00000000f6a00000)
  eden space 40960K,  43% used [0x00000000f3800000, 0x00000000f4994650, 0x00000000f6000000)
  from space 5120K,   0% used [0x00000000f6000000, 0x00000000f6005040, 0x00000000f6500000)
  to   space 5120K,   0% used [0x00000000f6500000, 0x00000000f6500000, 0x00000000f6a00000)
 concurrent mark-sweep generation total 79872K, used 5130K [0x00000000f6a00000, 0x00000000fb800000, 0x0000000100000000)
 Metaspace       used 3945K, capacity 4568K, committed 4864K, reserved 1056768K
  class space    used 434K, capacity 460K, committed 512K, reserved 1048576K

从运行结果可以看出:
堆内存的最大容量为200M,其中新生代设置为50M,按照8:1:1的比率可以计算出Eden大小为40M,From Survivor和To Survivor都为5M,-XX:TargetSurvivorRatio=60表示当对象所占空间达到了Survivor的60%时就会动态调整所设阈值,5*60%=3,从打印日志中也进行了证实,最大不超过-XX:MaxTenuringThreshold所设置的阈值大小(本次测试为3M),当运行到byte3,byte4,byte5被创建时,此时达到了所设置的阈值,因此会通过公式min(MaxTenuringShold,当前对象年龄),因此会输出Desired survivor size 3145728 bytes, new threshold 1 (max 3),此时Survivor中的所有对象都会被晋升到老年代,此时From Survivor和To Survivor区域都为空了,当下一次再有新的对象被创建时,此时阈值又调整回了3,并且新创建的对象的年龄都为1,Desired survivor size 3145728 bytes, new threshold 3 (max 3) -age 1: 56 bytes, 56 total证实了这一点

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值