Java垃圾回收机制
在Java中,解除分配内存的过程由垃圾收集器自动处理。
不同类型内存的判断方式
- 对象回收 - 引用计数(解决不了循环引用问题)
- 对象回收 - 可达性分析
- 简单说,将对象及其引用关系看作一个图,选定活动的对象作为GC Root,所有的GC Root将形成一个集合。
- 可作为GC Root的对象有:虚拟机栈中的正在引用的对象、本地方法栈中正在引用的对象、静态属性引用的对象、方法区常量引用的对象。
- 然后跟踪引用链条,如果一个对象和GC Root集合之间不可达,也就不存在引用关系,即可认定其是可回收对象。
- 引用类型:强引用、软引用、弱引用、幻象引用。
- 可达性级别:强可达、软可达、弱可达、幻想可达、不可达。
- 方法区回收
垃圾收集算法
-
标记清除算法
首先标识出所有要回收的对象,然后进行清除。标记、清除过程效率有限,有内存碎片化的问题,不适合特别大的堆;收集算法基本基于标记清除的思路进行改进。
-
复制算法
划分两块同等大小的区域,收集时将活着的对象复制到另一个区域。拷贝过程中将对象顺序放置,就可以避免内存碎片化。复制+预留内存,有一定的浪费。
-
标记整理算法
类似于标记清除,但为避免内存碎片化,它会在清理过程中将对象移动,以确保移动后的对象占用连续的内存空间。
分代收集
堆内存分新生代与老年代,新生代 : 老年代 = 1 : 2 。
新生代又分S0、S1、Eden,Eden : S0 : S1 = 8 : 1 : 1 。
垃圾收集器
-
串行收集器 - Serial GC
单个线程来执行所有垃圾收集工作,适合单处理器机器。新生代采用复制算法,老年代采用标记整理算法。
-
并行收集器 - Parallel GC
多线程并行执行,server模式JVM的默认GC选择,新生代老年代都是并行进行,可设置GC时间和吞吐量等值,可自动进行适宜性调整Eden、Survivor大小和MaxTenuringThreshold的值,是吞吐量优先的GC。
-
并发收集器 - CMS (Concurrent Mark Sweep) GC
专用老年代,基于标记清除算法,设计目标是尽量减少停顿时间。
-
并行收集器 - ParNew GC
新生代GC实现,实际是Serial GC的多线程版本。
-
并发收集器 - G1
针对大堆内存设计的收集器,兼顾吞吐量和停顿时间,JDK9后为默认选型,目标是替代CMS。G1将对分成固定的大小区域,区域间是复制算法,但整体上看是标记整理算法,可有效避免内存碎片。