09–内存分配策略–对象优先在Eden分配
1、测试
1.1、代码
/**
*
* @描述:对象优先在Eden分配
* @author feiZhou
* @date 2018年11月21日上午8:30:41
* @version 1.0
*/
public class EdenAllocation1 {
private static final int _1MB = 1024*1024;
/**
* VM参数:-XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8
*/
@SuppressWarnings("unused")
public static void main(String[] args) {
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];
}
}
2.2、日志
[GC (Allocation Failure) [DefNew: 7808K->603K(9216K), 0.0062181 secs] 7808K->6747K(19456K), 0.0074891 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
def new generation total 9216K, used 4781K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
eden space 8192K, 51% used [0x00000000fec00000, 0x00000000ff014930, 0x00000000ff400000)
from space 1024K, 58% used [0x00000000ff500000, 0x00000000ff596d10, 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 3199K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 346K, capacity 388K, committed 512K, reserved 1048576K
3、分析
3.1、JVM配置
1、 堆内存20MB,其中新生代10MB,老年代10MB;
2、 新生代区域的分配比例是8:1:1,也就是说;
1、 eden区8192K;
2、 from区1024K;
3、 to区1024K;
4、 新生代总可用空间为9216KB(Eden区+1个from区的总容量);
3、 使用Serial/SerialOld组合收集器;
3.2、当 allocation1、allocation2、allocation3 分配进内存的时候
其他系统对象:7808K-210243K=1664K
3.3、当 分配allocation4对象 的时候
由于eden去空间不够,发生Minor GC
3.3.1、日志解读
[GC (Allocation Failure) [DefNew: 7808K->603K(9216K), 0.0062181 secs] 7808K->6747K(19456K), 0.0074891 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
GC :
代表发生了一次垃圾回收,前面没有Full修饰,表明这时一次Minor GC;
Allocation Failure:
表明本次引起GC的原因是因为在年轻代中没有足够的空间能够存储新的数据了。
7808K->603K(9216K):
三个参数分别为:GC前该内存区域(年轻代)使用容量,GC后该内存区域使用容量,该内存区域总容量。
7808K->6747K(19456K)
三个参数分别为:堆区垃圾回收前的大小,堆区垃圾回收后的大小,堆区总大小。
0.0074891 secs
代表本次新生代GC耗时
年轻代回收空间
7808K-603K=7205K=7.0361M
堆回收空间
7808K-6747K=1061K
进入老年代空间
7205K-1061K=6144K=6M
3.3.2、分析
因为allocation1、 2、 3三个对象是强引用,不会被回收,所以都是存活。
产生这次垃圾收集的原因是为allocation4分配内存时, 发现Eden已经被占用了6MB, 剩余空间已不足以分配allocation4所需的4MB内存, 因此发生Minor GC。
垃圾收集期间虚拟机又发现已有的三个2MB大小的对象全部无法放入Survivor空间(Survivor空间只有1MB大小),所以只好通过分配担保机制,将allocation1、 2、 3转移到老年代去。
最后Eden空闲出来了就可以放allocation4,消耗内存4M。
因此程序执行完的结果是Eden占用4MB(被allocation4占用) , Survivor空闲, 老年代被占用6MB(被allocation1、 2、 3占用) 。
通过GC日志可以证实这一点。 (tenured generation total 10240K, used 6144K)