HotSpot中Parallel Scavenge/Parallel Old与Serial/Serial Old内存分配策略区别

本文探讨Java HotSpot虚拟机中,Parallel Scavenge/Parallel Old与Serial/Serial Old垃圾收集器在内存分配策略上的区别。对象通常在新生代的Eden区分配,当空间不足时触发Minor GC。大对象可能直接进入老年代,长期存活的对象也会晋升。Parallel Scavenge不支持某些Serial Old的内存分配策略,如对象年龄阈值和空间分配担保。
摘要由CSDN通过智能技术生成

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来。

关于JVM的垃圾收集技术,前面的文章中已经介绍虚拟机中的垃圾收集器体系以运作原理,现在我们再一起来探讨一下给对象分配内存的那点事儿。

对象的内存分配,往大方向讲,就是在堆上分配(但也可能经过JIT编译后被拆散为标量类型并间接地栈上分配 ),对象主要分配在新生代的Eden区上。少数情况下也可能会直接分配在老年代中,分配的规则并不是百分之百固定的,其细节取决于当前使用的是哪一种垃圾收集器组合,还有虚拟机中与内存相关的参数的设置。

接下来我们将会讲解几条最普遍的内存分配规则,并通过代码去验证这些规则。接下来的代码的是在使用Parallel Scavenge/Parallel Old 收集器下与Serial/Serial Old收集器下的内存分配和回收的策略的对比.

注意:Serial/Serial Old收集器与ParNew/Serial Old收集器组合的规则也基本一致

验证对象优先分配在新生代的Eden区中:

对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。虚拟机提供了-XX:+PrintGCDetails这个收集器日志参数,告诉虚拟机在发生垃圾收集行为时打印内存回收日志,并且在进程退出的时候输出当前的内存各区域分配情况。
现在我们执行以下代码:

/**
    *VM参数:-verbose:gc-Xms20M-Xmx20M-Xmn10M-XX:+PrintGCDetails
    -XX:SurvivorRatio=8
    */
public class SeeMinorGC {
   
     private static final int _1MB= 1024*1024;

    public static void testAllocation(){

    byte[] allocation1,allocation2,allocation3,allocation4;
    allocation1 = new byte[2*_1MB];
    allocation2 = new byte[2*_1MB];
    allocation3 = new byte[2*_1MB];
    allocation4 = new byte[4*_1MB];//是否会出现一次Minor GC

    }

    public static void main(String args[]) {
           testAllocation();
    }
}

estAllocation()方法中,尝试分配3个2MB大小和1个4MB大小的对象,在运行时通过-Xms20M、-Xmx20M、-Xmn10M这3个参数限制了Java堆大小为20MB,不可扩展,其中10MB分配给新生代,剩下的10MB分配给老年代。-XX:SurvivorRatio=8决定了新生代中Eden区与一个Survivor区的空间比例是8:1

Parallel Scavenge/Parallel Old收集器下的GC日志:

Heap
 PSYoungGen      total 9216K, used 6799K [0xe6600000, 0xe7000000, 0xe7000000)
  eden space 8192K, 83% used [0xe6600000,0xe6ca3fc0,0xe6e00000)
  from space 1024K, 0% used [0xe6f00000,0xe6f00000,0xe7000000)
  to   space 1024K, 0% used [0xe6e00000,0xe6e00000,0xe6f00000)
 ParOldGen       total 10240K, used 4096K [0xe5c00000, 0xe6600000, 0xe6600000)
  object space 10240K, 40% used [0xe5c00000,0xe6000010,0xe6600000)
 Metaspace       used 1619K, capacity 2202K, committed 2328K, reserved 4400K

从输出的结果也可以清晰地看到“eden space 8192K、from space 1024K、to space 1024K”的信息,新生代总可用空间为9216KB(Eden区+1个Survivor区的总容量)。

执行testAllocation()时,allocation1、allocation2、allocation3三个对象顺利的被分配在了eden区。当分配allocation4对象的时候,发现新生代剩余的空间已经不足以存放allocation4对象,所以该对象直接被分配在老年代。此时并不会发生GC。

对于上述代码,Serial/Serial Old收集下的GC日志为:

[GC[DefNew:6651K->148K(9216K),0.0070106 secs]6651K->6292K(19456K),
0.0070426 secs][Times:user=0.00 sys=0.00,real=0.00 secs]
Heap
def new generation total 9216K,used 4326K[0x029d0000,0x033d0000,0x033d0000)
eden space 8192K,51%used[0x029d0000,0x02de4828,0x031d0000)
from space 1024K,14%used[0x032d0000,0x032f5370,0x033d0000)
to space 1024K,0%used[0x031d0000,0x031d0000,0x032d0000)
tenured generation total 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值