1、如何确定某个对象是垃圾
1)引用计数法:一个对象没有任何与之关联的引用。无法解决循环引用问题。
2)可达性分析:在“GC roots”和一个对象之间没有可达路径。不可达对象不等于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。
2、垃圾回收算法
1)标记-清除算法(Mark-Sweep)
最基础的垃圾回收算法,分为两个阶段:标注和清除。(内存碎片化)
2)复制算法(Copying)
将内存划分为等大小的两块,每次只使用其中一块,当这一块内存满后将存活的对象复制到另一块,把已使用的内存清掉。(不易产生碎片,但可用内存只有一半)
3)标记-整理算法(Mark-Compact)
结合了以上两个算法,标记阶段和Mark-Sweep算法相同,标记后不是清理对象,而是将存活对象移向内存的一端,然后清除端边界外的对象。
4)分代收集算法
- 分代收集算法是目前大部分JVM采用的方法,核心思想是根据对象存活的不同生命周期将内存划分为不同的域。
- 老生代:每次垃圾回收时只有少量对象需要被回收。
- 新生代:每次垃圾回收时都有大量对象需要被回收。
- 新生代一般采取Copying算法,因为大部分对象是需要回收的,即要复制的操作比较少。通常不是按照1:1划分新生代,一般将新生代划分为一块较大的Eden空间和两个较小的Survivor空间,每次使用Eden空间和其中一块Survivor空间,当进行回收时,将该两块空间中还存活的对象复制到另一块Survivor空间中。
5)老生代一般采用Mark-Compact算法
6)方法区的永生代
3、垃圾收集器
1)Serial/Serial Old收集器:
最基本、最悠久的收集器。单线程,必须停止其他所有工作的线程。
2)ParNew收集器
是Serial多线程版本,其余行为与Serial完全一样。
3)Parallel Scavenge/Parallel Old(并行回收)收集器
- 并行的多线程收集器,目标是达到可控的吞吐量(Throughput)。
- 吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
- 提供两个参数用于精确控制吞吐量,分别是控制最大垃圾收起停顿时间(-XX:MaxGCPauseMillis)参数、设置吞吐量大小(-XX:GCYimeRatio)参数。
- 还有一个开关参数-XX:UseAdaptiveSizePolicy,如果打开就不需要手动指定新生代大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数,只需要把基本的内存数据设置好(如-Xmx设置最大堆),然后使用MaxGVPauseMillis参数或GCTimeRation参数给虚拟机设立一个优化目标。
4)CMS收集器
一种以获取最短回收停顿时间为目标的收集器,基于“标记-清除”算法实现的,运作过程分为4个步骤:初始标记、并发标记、重新标记、并发清除。其中,初始标记、重新标记这两个步骤仍然需要“Stop The World”。
5)G1收集器
并行与并发、分代收集、空间整理(标记整理算法,复制算法)、可预测的停顿时间的收集器。运作可划分为:初始标记、并发标记、最终标记、筛选回收。