JVM主要通过以下几种方式来判断对象是否需要回收:
引用计数法:JVM通过引用计数器来判断对象的引用数量,当引用数量为0时,表示对象可以被回收。
可达性分析算法:JVM通过根对象(如栈中的引用、静态变量等)出发,对对象进行可达性分析,判断对象是否可被访问到,如果不可达,则表示对象可以被回收。
年龄判断:对于分代垃圾回收算法,JVM会根据对象的存活时间来判断对象是否需要回收,存活时间较长的对象会被移到老年代,存活时间较短的对象会被回收。
标记阶段:在标记-清除、标记-整理等算法中,JVM会通过标记活动对象来判断哪些对象可以被回收。
这些方法结合起来,帮助JVM判断哪些对象可以被回收,从而进行垃圾回收操作。
垃圾回收算法 | 区别 |
---|---|
标记-清除算法 | 通过标记所有活动对象,然后清除所有未标记的对象来回收内存。但会产生内存碎片 |
复制算法 | 将内存分为两块,每次只使用其中一块,当这一块内存满了,就将存活的对象复制到另一块内存中,然后清除当前内存中的所有对象。不会产生内存碎片 |
标记-整理算法 | 类似于标记-清除算法,但在清除之后会将存活的对象向一端移动,整理出连续的内存空间。减少内存碎片的产生 |
分代算法 | 将内存分为新生代和老年代,新生代使用复制算法,老年代使用标记-整理算法,根据对象的存活时间来进行不同的垃圾回收处理 |
并发标记清除算法 | 在标记和清除阶段尽可能与程序并发执行,减少停顿时间 |
特征 | CMS | G1 | ZGC |
---|---|---|---|
垃圾回收类型 | 并发标记-清除 | 并发标记-整理 | 并发标记-整理 |
目标 | 减少停顿时间 | 综合性能和停顿时间 | 低停顿时间和高吞吐量 |
内存分区 | 以老年代为主 | 将堆划分为多个区域 | 不需要分代,整个堆都是一致的 |
停顿时间 | 有可能出现较长的停顿时间 | 相对较稳定的停顿时间 | 尽可能短的停顿时间 |
内存占用 | 高 | 中等 | 低 |
适用场景 | 适用于内存较大、应用线程较少的场景 | 适用于大内存、多核处理器的场景 | 适用于需要低延迟和大堆的场景 |
这些垃圾回收器各有其特点,可以根据具体的应用场景和需求来选择最合适的垃圾回收器。