前面有说到堆的可用内存少于预期值。这与GC的算法有关,被其贪掉了。 算法
GC主要是对堆的内存进行管理,用到的算法有 对象
1.标记算法: 内存
实现分为两个阶段,一:标记阶段; 二:清除阶段。经过根标记全部可达对象;在清除阶段时清除没有标记的对象。 基础
这就堆区分活动对象与非活动对象的方式。 垃圾回收
2.复制算法: 时间
将内存空间分为两块,每次只使用其中一块,在垃圾回收时将存活对象复制到未使用的内存中,以后清除正在使用的内存(全部的对象)。这时这两块内存的角色就互换了,然后交替重复。这就是为何新生代分为eden,s0,s1.并且s0与s1同样。而且系统会保留一个用来角色互换。s0和s1也称为survivor空间 vi
3.标记压缩法: 压缩
在标记算法基础上添加了对内存的整理,由于若是单纯的删除会产生不少的零碎。因此对内存进行了整理,使其能够连续。在老年代中用到 实例
4.分代算法: 管理
将内存区间根据对象分红几块(堆中分红新生代与老年代)。根据每块内存区间的特色使用不一样的回收算法
5.分区算法:
将整个堆空间划分红连续的不一样小区间。每一个小区间都独立使用。这种算法是能够控制一次回收多少的空间。由于若是堆空间越大,那么GC一次所要的时间就越长,从而产生停顿也就越长。分区会减小GC所产生的停顿
最后的归总:
新生代中: 在eden先标记活动对象 -> 将活动对象复制到s0/s1中,清空eden -> 标记s0/s1的活动对象 ->复制到老年代中,清除s0/s1。
全部将建立的实例都在新生代中。新生代回收的频率是很高的,但每次回收耗时都很短。
老年代中:标记活动对象 -> 清除非活动对象 -> 整理老年代中的空间
在通过屡次GC后还存活下来的实例把它放到老年代中,老年代回收次数少,且耗时长。