> gc垃圾回收期
1.什么时候出发gc:
手动触发:当前程序去调用System.gc().注意:GC回收的时候程序会停止运行同时回收的过程中,会消耗大量的系统性能,所以,一般情况下我们不会主动的去调用gc回收方法
自动出发:根据Eden区和FromSpace区的内存大小来决定,当内存大小不足时,则会启动GC线程并停止应用线程
程序在申请内存的时候,系统(JVM)发型呢内存不足,这个时候就会出发GC
2.GC回收算法
标记清楚
分为两个步骤,第一个步骤就是标记,也就是标记所有标记需要回收的对象,这种算法有点事简单,缺点就是效率问题.还有一最大的缺点就是空间问题.标记清楚之后会产生大量不连续的内存碎片,当程序在以后的运行过程中需要分配较大的对对象时无法找到足够的连续内存而造成内存空间浪费
标记复制:复制将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当这一快的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉,这样使得每次都是对其中的一块进行内存回收.,内存分配时也就不用考虑内存碎片等复杂情况,只是这种算法的代价是将内存缩小为原来的一半
标记整理:标记整理算法与标记清楚算法很相似.但最显著的区别是:标记清楚的算法仅对不存活的对象激进型处理,剩余存活对象不做任何处理,造成内存碎片;而标记整理算法不仅对不存活对象进行处理清楚,还对剩余的存活对象进行整理,重新整理,因此其不会产生内存碎片
分代收集:
新生代 -> 老年代 -> 永久代
新生代:尽可能快速收集回收掉生命周期短的对象,一般情况下创建的对象都放入到新生代中
老年代:老年代中对象的生命周期比较长.新生代经历过N次回收以后,任然存活的对象
永久代:主要用于存放静态文件,如:Java类,方法
在新生代中,.每次垃圾收集时都发现有大批对象死去,只有少量存活,那就蒜用复制算法,只需要付出少量存活对新娘的复制成本就可以完成收集
3.新生代总对象如何向老年代过度
新生代分三个区域:eden,survivor0,survivor1三个区域,大量的对象都在eden区域,在gc的时候,先将eden区存活的对象复制到survivor0区域,然后清空了eden。当survivor0区域满了以后,则将eden和survivor0区域中存活的对象复制到survivor1区域。然后清空eden和survivor0区域。把survivor1中的数据全部复制到survivor0区域中。经过反复的gc,当survivor1区域不足以放下eden和survivor0区域中的存活对象,就直接将存活的对象放入到老年代。
老年代中因为对象存活率高,没有额外控件对他进行分配担保,就必须用标记清楚或者标记整理
注意:在jdk8的时候java飞起了永久代,但是并不意味着我们以上的结论失败.因为java提供了永久代类似的叫做"元空间"的技术