如何确定垃圾
- 引用计数法
通过引用计数来判断定对象,会存在循环引用的问题,即使对象以后不会再使用,也不会被垃圾回收器进行回收 - 可达性分析
为了解决引用计数带来的循环引用问题,Java使用了可达性分析的方法,通过一系列的“GC-ROOT”对象作为起始搜索点,如果从任何一个GC-ROOT和一个对象间有可达路径,那么对象是存活的,不能被回收。不可达对象至少经过两次标记之后才会面临回收。可以作为GC-ROOT的对象可以是a.虚拟机栈中局部变量的引用,b.方法区静态变量和常量的引用,c.本地方法栈中的引用
垃圾回收算法
-
标记清除算法
算法过程分为标记和清除两个阶段,算法完成后会存在内存碎片
清除.gif -
复制算法
将内存容量分为两部分,每次只使用其中的一块,当内存满后,将存活的对象复制到另一块上面去。虽然解决了内存碎片问题,但内存利用率不高。如果存活对象增多的话,复制算法的效率会大大降低。
复制.gif -
标记整理算法
结合标记清除算法和标记复制算法,标记存活的对象后,将存活的对象移动到内存的另一端,然后清除边界外的对象。
标记整理.gif -
分代收集算法
目前大部分JVM的GC新生代都采用复制算法,新生代的对象大部分都是可回收的,所以采用复制算法并不会很大的影响效率,通常比例并不是按照1:1进行划分。eden:from-survivior:to-survivor=8:1:1。老年代因为每次只回收少量对象,因而采用标记清除和标记整理算法。
分代收集算法.gif -
分区收集算法
分区算法则是将整个堆空间划分为连续的不同小空间,每个小区独立使用,独立回收,这样做的目的是可以一次控制回收多少空间,根据目标停顿时间,每次合理底回收若干小空间,从而减少一次GC所产生的停顿。
image.png