深入JVM学习------垃圾回收算法
这次我们主要说四种垃圾回收算法,分别是标记—清除,标记—整理,复制以及分代回收。
标记—清楚算法
在标记阶段,像图中,collector会从根对象开始遍历,发现被引用的对象就做上标记。
在清除阶段,collector会对堆内存从头到尾进行遍历,将没有标记的对象进行回收,释放内存。
该方法优点:速度快。
该方法缺点:存在大量的零碎内存,当有需要大内存的对象要存储时会导致内存溢出。
标记—整理算法
在标记阶段,该方法也是会从根对象开始遍历,发现被引用的对象就做上标记。
在整理阶段,该方法会对堆内存从头到尾进行遍历,将没有标记的对象进行回收,释放内存。然后再将剩余对象内存进行整理。
该方法优点:不会出现零碎的内存碎片,充分的使用了内存。
该方法缺点:速度慢。
复制算法
该算法将内存分为了两部分,一个FORM区,一个TO区。collector对FROM区中存活的对象复制到TO区中。
同时清除FROM区中所有的对象内存,紧接着将TO区变为FROM区,FROM区变为TO区
该方法优点:速度快(当然如果堆中没有要回收对象,他要把全部对象复制到TO区,速度还是会慢)不会出现零碎的内存碎片,充分的使用了内存。
该方法缺点:占用双倍内存。
分代回收算法
如果上面方法懂了的话,那么分代回收就能接着看了。
分代算法是将堆内存划分为新生代和老年代两个部分。新生代包括伊甸园、幸存区FROM、幸存区TO。
每个对象在创建时都会被分配在伊甸园区,当伊甸园空间不足时会触发Minor GC,并将存活对象使用copy复制到幸存区TO中,存活对象“年龄”+1并且交换FROM与TO。
当然触发Minor GC时会引发STW(Stop The World),指停止其它线程活动,因为垃圾回收设计复制,改变了对象的地址,其他线程如果运行,可能会出现按原地址访问找不到对象的情况。
当对象“年龄”超过阈值时就会晋升至老年代,阈值是可以设置的,最大为15.
当老年代空间不足,会尝试触发Minor GC,如果之后空间仍不足,那么会触发Full GC(时间较久),同时也会引发STW。
如果一个对象的大小超过了伊甸园总大小,那么他会直接晋升至老年代。
如果一个线程因堆内存不足报错时不会停止其它线程的执行。