一、为什么要分代?
其实不分代也能完成GC,只不过不分代的话,会扫描整个堆内存,会很耗时。
其次对象都有自己的生存周期,大部分对象都是朝生夕死的,所以分代会提高扫描的效率。
二、既然分代了,直接分一个年轻代和老年代不就行了,为何要有survivor区?
survivor存在的意义就是减少送到老年代的对象,进而减少FullGC的发生,survivor筛选的16次MinorGC还能存活的对象,才能送往到老年代中。
没有survivor区,则eden区每次minor后都会把存活的对象存到老年代中,那么老年代很快就会被填满,从而触发FullGC,老年代的空间要比年轻代打,
触发FullGC会比较耗时的。减少老年代的内存大小,会很快被填满,会增加FullGC的频率;增加老年代的内存大小,FullGC执行的时间长。
三、既然有了survivor区了,为何还要分两个呢?
设置两个survivor区最大的好处就是避免了碎片化。
如果不设置两个,eden区每次minorGC后把存活的对象放到survivor,survivor原有的对象和新进来的对象内存可能不会连续,就会导致了碎片化,会严重影响性能。
至于为啥不分成三个、四个、五个等survivor区,这个应该是经过权衡的。
四、为何年轻代中,Eden区要比survivor大很多呢?
如果Eden区设置的小,则很快就会被塞满,Eden区被塞满后就会触发minorGC,就是减少minorGC的频率。
五、minorGC和FullGC什么时候触发?
minorGC:
Eden区满了;
FullGC执行会先执行minorGC
FullGC:
调用了System.gc,JVM是建议执行FullGC,但是不是必然的;
老年代空间不足;
方法区空间不足;
六:年轻代如何运行的?
刚开始三个区域都是空的
一段时间后对象存在于Eden区和From区,To区仍然是空的
第一次Minor触发
(
Eden区所有的存活对象都存放到To区,From区的对象根据自身的年龄值来决定去向(年龄达到一定的值后对象直接移动到老年代中,没有达到阀值则被复制到To区),有个疑问,From区的对象是否会有没用的对象?
然后清空Eden区和From区
From区和To区交换角色(要保证Survivor To区一直是空的)
)
经过一段时间后对象存在于Eden区和From区,To区仍然是空的
第二次Minor触发
。。。。
。。。
直到触发过程中,To区被填满,会把对象都移动到老年代中,至此年轻代中都为空了,此时可能会触发FullGC,也可能不会,看老年代的内存大小了。
这个过程图可以参考一下:https://www.cnblogs.com/andy-zhou/p/5327288.html#_caption_13
七:FullGC:
清除的是老年代中无用的对象。
参考:https://blog.csdn.net/u012799221/article/details/73180509