HotSpot的内存分配的基本策略是对象优先在Eden区分配,如果Eden区剩余空间不足以分配内存时,触发minorGC,将Eden区数据复制到Survior区,如果Survior区空间不够,则将存活对象复制到Old区域。测试GC回收的简单代码:
/** * * @title :TestMain * @description :-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails * @update :2014-12-20 下午4:22:52 * @author :172.17.5.73 * @version :1.0.0 * @since :2014-12-20 */ public class TestMain { private static final int CONST_MB = 1024*1024; public static void main(String[] args) { byte[] location1 = new byte[2*CONST_MB]; byte[] location2 = new byte[2*CONST_MB]; byte[] location3 = new byte[2*CONST_MB]; byte[] location4 = new byte[2*CONST_MB]; location1 = null; byte[] location5 = new byte[2*CONST_MB]; byte[] location6 = new byte[2*CONST_MB]; } }
设置运行时JVM参数为 -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails,则在默认的SurviorRation=8:1的情况下,Eden区占8M,From 、To各占1M,Old区占10M。运行代码结果如下:
[GC [DefNew: 6692K->364K(9216K), 0.0134696 secs] 6692K->6508K(19456K), 0.0135438 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] Heap def new generation total 9216K, used 6924K [0x31740000, 0x32140000, 0x32140000) eden space 8192K, 80% used [0x31740000, 0x31da7f80, 0x31f40000) from space 1024K, 35% used [0x32040000, 0x3209b248, 0x32140000) to space 1024K, 0% used [0x31f40000, 0x31f40000, 0x32040000) tenured generation total 10240K, used 6144K [0x32140000, 0x32b40000, 0x32b40000) the space 10240K, 60% used [0x32140000, 0x32740030, 0x32740200, 0x32b40000) compacting perm gen total 12288K, used 140K [0x32b40000, 0x33740000, 0x36b40000) the space 12288K, 1% used [0x32b40000, 0x32b63140, 0x32b63200, 0x33740000) ro space 10240K, 45% used [0x36b40000, 0x36fc2710, 0x36fc2800, 0x37540000) rw space 12288K, 54% used [0x37540000, 0x37bc6488, 0x37bc6600, 0x38140000)
可以推测GC的流程如下:当为变量location4分配内存时,eden区已占用6692K,剩余(8192K-6692K=1500K),而此时location4需要2M(2048K),则此时会触发一次MinorGC,Survior的From大小为1M,不够存放location1、2、3三个对象(6M),则这三个对象直接进入Old区。回收后Eden空间为8M-364K,足够分配location4、location5、location6三个对象。所以整个过程只发生了一次MinorGC,程序运行结束时Old区占据6M,Eden区占据6M。
大致的流程我可以思考清楚,只是还有一点疑问就是,为什么最初只有location1-3三个对象,总共6M=6144K,但是首次MinorGC时Young区使用的空间却是6692K呢?那剩余的548K是被谁占用的呢??疑惑!通过GC日志,可以理解HotSpot内存分配策略之对象优先在Eden区进行分配的原则。