09、JVM实战:内存分配策略:对象优先在Eden分配

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)