jvm运行时内存
在堆中主要分为两个区域
新生代 (伊甸园区Eden,幸存区From、幸存区To) 用完后即可丢弃,经常GC
新生代的堆空间分配大小可以通过-XX:SurvivorRatio进行设置
老年代 长时间使用的对象,偶尔GC
新创建的对象先放在新生代的伊甸园区,但是当新创建的对象所占用的内存过大则会放在老年代
由于java会频繁创建对象,所以新生代会频繁触发Minor GC进行垃圾回收
先简单介绍一下minor GC,主要流程是复制–清空–交换,采用复制算法,执行的回收速度很快
–》Eden不够时会触发第一次minor GC,将Eden和From区GC后存活的对象移到To区中,同时这些幸存者对象的年龄+1
–》将To中的幸存者移到From中作为第二次minor GC 的扫描对象,此时Eden空间充足的话可以继续分配对象
–》Eden空间又被填满后再进行第二次minor GC,此时除了扫描Eden区,还要查找幸存区有无需要继续存活的对象。将Eden和From区中需要存活的对象重复第一次的操作,移到To区,对象年龄+1
–》在上述操作中,待对象年龄超过15,则晋升到老年代中
当触发minor GC时需要引发一次STW,将其他线程暂停,完成From和To的交换后其他线程才可进行,暂停时间较短,因为在交换过程中会改变对象地址,如果其他线程不停止,会出现混乱
在老年代中主要执行major GC,执行major GC前至少执行一次minor GC,但是由于老年代中的对象比较稳定,所以不会频繁执行major GC,且major GC 执行速度比较慢,先扫描后回收,采用标记清除算法
–》当老年代空间也被填满后,会先执行Full GC,GC后空间还是不足则会抛出OOM(Out of Memory)异常
Full GC,也会出现在上述所提到的创建的对象过大放在老年代时发现老年代也放不下,此时会进行full GC操作