JVM学习-----java7与Java8新生代GC发生了什么

测试代码

VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

verbose:gc 表示输出虚拟机中GC的详细情况.
-Xms20m:表示堆的最小值为20M
-Xms20m:表示堆的最大值同样设置为20M,
-Xmn10M:表示新生代分配10M
-XX:SurvivorRatio=8:表示新生代的eden区:from区:to区:8:1:1
-XX:+PrintGCDetails 打印GC日志到控制台
package com.wuhulala.jvm.gc;

/**
 * 新生代GC 
 *
 * @author xueaohui
 * @version 1.0
 * @date 2017/3/19
 * @link https://github.com/wuhulala
 */
public class MinorGC {

    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[_1MB * 2];
        allocation2 = new byte[_1MB * 2];
        allocation3 = new byte[_1MB * 2];
        allocation4 = new byte[_1MB * 5]; //出现一次MinorGC

    }



}

java8_1.8.0_111

日志

    /**
     *  Heap java8
     *PSYoungGen      total 9216K, used 7789K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
     *eden space 8192K, 95% used [0x00000000ff600000,0x00000000ffd9b7d8,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 3215K, capacity 4494K, committed 4864K, reserved 1056768K
     *class space    used 355K, capacity 386K, committed 512K, reserved 1048576K
     */

从上面结果来看 java8 默认使用的新生代垃圾收集器是PSYoungGen(Parallel Scavenge) 它是并行收集器
注重于吞吐量的指标,吞吐量可以简单理解为 CPU执行用户程序的时间。
如果没有太多的操作 ,那么GC次数肯定也会很少,所以就不用过于关注GC的时候的停顿时间。
在这种应用场景之下,我们就可以关注一下 吞吐量了(吞吐量=运行用户代码时间/(运行用户代码时间+GC消耗的时间))

//在注释掉**allocation4 = new byte[_1MB * 4]; **此语句之后 我发现GC打印日志如下
    //Heap
    //PSYoungGen      total 9216K, used 7789K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
    //eden space 8192K, 95% used [0x00000000ff600000,0x00000000ffd9b7d8,0x00000000ffe00000)
    //from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
    //to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
    //ParOldGen       total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
    //object space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000)
    //Metaspace       used 3216K, capacity 4494K, committed 4864K, reserved 1056768K
    //class space    used 355K, capacity 386K, committed 512K, reserved 1048576K

可见老年代没有任何对象
在对allocation4分配内存之后
新生代内存没有发生变化 老年代的内存刚好4M内存 与allocation4的内存大小对应
那么老年代的估计就是allocation4了
但是为了解决这个疑惑
那么我为allocation4分配5M内存,查看日志

    // ParOldGen       total 10240K, used 5120K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)

那就可以有了如下解释
PS收集器为了保证吞吐量 并且在新生代没有足够的内存的情况下 直接把新的大对象分配到了老年代

java7_1.7.0_15


    /**
     * Heap java7
     *def new generation   total 9216K, used 4779K [0x331b0000, 0x33bb0000, 0x33bb0000)
     *eden space 8192K,  53% used [0x331b0000, 0x335ed7f0, 0x339b0000)
     *from space 1024K,  42% used [0x33ab0000, 0x33b1d660, 0x33bb0000)
     *to   space 1024K,   0% used [0x339b0000, 0x339b0000, 0x33ab0000)
     *tenured generation   total 10240K, used 6144K [0x33bb0000, 0x345b0000, 0x345b0000)
     *the space 10240K,  60% used [0x33bb0000, 0x341b0030, 0x341b0200, 0x345b0000)
     *compacting perm gen  total 12288K, used 203K [0x345b0000, 0x351b0000, 0x385b0000)
     *the space 12288K,   1% used [0x345b0000, 0x345e2fd8, 0x345e3000, 0x351b0000)
     *ro space 10240K,  45% used [0x385b0000, 0x38a37290, 0x38a37400, 0x38fb0000)
     *rw space 12288K,  54% used [0x38fb0000, 0x3963ace8, 0x3963ae00, 0x39bb0000)
     */

java7 默认使用的是Serial 收集器,它是最原始的收集器。
由于survivor区没有足够的内存存放,
所以allocation1 allocation2 allocation3 直接进入老年代
在老年代的是allocation1 、allocation2、 allocation3 内存占6M
在新生代的时候是新的allocation4 内存占4M

===================2017.03.19 PM=========================

经查阅资料得知:
-XX:PretenureSizeThreshold 参数可以配置一个内存阀值,大于这个值的对象直接分配在老年代之中。
在Parallel Scavenge收集器中此参数无效。
那么在java7中allocation4没有进入老年代就可以解释了。
在VM参数加入
-XX:PretenureSizeThreshold=3145728 (3M)

打印日志:

Heap
 def new generation   total 9216K, used 7348K [0x331b0000, 0x33bb0000, 0x33bb0000)
  eden space 8192K,  89% used [0x331b0000, 0x338dd0b8, 0x339b0000)
  from space 1024K,   0% used [0x339b0000, 0x339b0000, 0x33ab0000)
  to   space 1024K,   0% used [0x33ab0000, 0x33ab0000, 0x33bb0000)
 tenured generation   total 10240K, used 4096K [0x33bb0000, 0x345b0000, 0x345b0000)
   the space 10240K,  40% used [0x33bb0000, 0x33fb0010, 0x33fb0200, 0x345b0000)
 compacting perm gen  total 12288K, used 185K [0x345b0000, 0x351b0000, 0x385b0000)
   the space 12288K,   1% used [0x345b0000, 0x345de658, 0x345de800, 0x351b0000)
    ro space 10240K,  45% used [0x385b0000, 0x38a37290, 0x38a37400, 0x38fb0000)
    rw space 12288K,  54% used [0x38fb0000, 0x3963ace8, 0x3963ae00, 0x39bb0000)

the space 10240K, 40% used [0x33bb0000, 0x33fb0010, 0x33fb0200, 0x345b0000)

由上可知allocation4现在在老年代中
占用了40%的内存

tip: 大内存对象最好不要用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值