将这个堆内存划分成两块:新生代和老年代,刚刚创建的对象都在新生代,长久存活的对象都在老年代(老年代的垃圾回收很久发生一次,新生代的垃圾回收发生的比较频繁)
新生代又进一步划分成伊甸园Eden,幸存区From,幸存区To
新创建一个对象,会将这个对象放在eden伊甸园区,eden区占满之后,就会触发minor GC,复制eden区里面不能被回收的对象,复制到ServiceFrom区,然后清空eden区(此时只有ServiceFrom区有元素,其他两个区是空的)
然后再次创建对象会再次被放到eden区,等eden区满了之后,又触发一次minor GC,此时会将eden区和ServiceFrom区不能回收的对象会被复制到ServiceTo区,然后清空eden区和ServiceFrom区(此时只有ServiceTo区有元素,其他两个区是空的)
当再次创建对象会再次被放到eden区,等eden区满了之后,又触发一次minor GC,这次会将eden区和ServiceTo区不能回收的对象复制到ServiceFrom区中,然后清空eden区和ServiceTo区(此时只有ServiceFrom区有元素,其他两个区都是空的)
总结:每一次垃圾回收之后,ServiceFrom和ServiceTo两块区域只有一种区域里面有元素、
每次经过一次垃圾回收,剩余的对象年龄+1.当对象的年龄到达一定阈值(比如16)还没有被回收,那就会将这个对象迁移至老年代(除了这种情况要将对象放到老年代,还有当你创建了一个大对象,比如5M(这个值可以通过PretenureSizeThreshold这个参数进行设置,默认3M,即使Eden区有足够的空间来存放,也不会存放在Eden区,而是直接存入老年代)
老年代空间不足时,会先尝试触发Minor GC,如果之后空间还不足,则触发full GC,Major GC的速度一般会比Minor GC慢10倍以上
分代回收相关虚拟机参数:
设置JVM参数:
-Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc
Heap
//新生代10MB
def new generation total 9216K, used 1835K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
//伊甸园区
eden space 8192K, 22% used [0x00000000f9a00000, 0x00000000f9bcada0, 0x00000000fa200000)
//幸存区from和幸存区to
from space 1024K, 0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
to space 1024K, 0% used [0x00000000fa300000, 0x00000000fa300000, 0x00000000fa400000)//老年代
tenured generation total 10240K, used 0K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
the space 10240K, 0% used [0x00000000fa400000, 0x00000000fa400000, 0x00000000fa400200, 0x00000000fae00000)
compacting perm gen total 21248K, used 2973K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
the space 21248K, 13% used [0x00000000fae00000, 0x00000000fb0e7558, 0x00000000fb0e7600, 0x00000000fc2c0000)