1.分析算法
在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定这些对象之中哪些还 “存活”着。
1.1.引用计数算法
在对象之中添加一个引用计数器,每当有一个地方引用它时,计数器就加一;当引用失效时,计数器就减一;任何时刻计数器为零的对象就是不可能在被使用的。
1.2.可达性分析算法
这个算法的思路就是通过一系列称为 “GC Roots” 的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为 “引用链(Reference Chain)”如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。
在Java技术体系里面,固定可作为 GC Roots的对象包括以下几种:
- 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如当前正在运行的方法所使用到的参数、局部变量、临时变量等。
- 在方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量
- 在方法区中常量引用的对象,譬如字符串常量池里的引用
- 在本地方法栈中JNI(即通常说的Native方法)引用的对象
- 在Java虚拟机内部的引用,如基本数据类型对象的Class对象,一些常驻的异常对象等,还有系统类加载器
- 所有被同步锁(Synchronized关键字)持有的对象
- 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。
出了这些固定的GC Roots集合以外,根据用户所选用的垃圾收集器以及当前回收的内存区域不同,还可以有其他对象 “临时性” 地加入,共同构成完整GC Roots集合。
2.引用方式
无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象是否引用链可达,判定对象是否存活都和 “引用” 离不开关系。但是对于一些 “食之无味 弃之可惜” 的对象就显得无能为力。譬如我们希望某些对象:当内存空间足够时能保留在内存之中,当内存空间非常紧张时能够回收这些对象。所以在JDK1.2版之后,Java对于引用的概念进行了扩充,将引用分为了 强引用、软引用、弱引用和虚引用。
2.1.强引用
是最传统的的 “引用” 的定义,是指在程序代码之中普遍存在的引用赋值,即类似 “Object obj = new Object()” 这种引用关系。无论任何情况,只要强引用关系存在,垃圾收集器就永远不会回收掉被引用的对象。
2.2.软引用
软引用时用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK1.2版之后提供了SoftReference类来实现软引用
2.3.弱引用
弱引用也是用来描述那些非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK1.2版之后提供了WeakReference类来实现弱引用。
2.4.虚引用
虚引用也被称为 “幽灵引用” 或者 “幻影引用”,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK1.2版之后提供了 PhantomReference 类来实现虚引用
3.垃圾收集算法
垃圾收集算法的实现涉及大量的程序细节,且各个平台的虚拟机操作内存的方法都有差异,垃圾收集算法可以分为两大类 “引用计数式垃圾收集” 和 “追踪式垃圾收集”,这两类也常被称为 “直接垃圾收集” 和 “间接垃圾收集”。
3.1.分代收集理论
当前商业虚拟机的垃圾收集器,大多数都遵循了 “分代收集”的理论设计,分代收集名为理论,实质是一套符合大多数程序运行实际情况的经验法则,它建立在两个分代假说之上
- 弱分代假说:绝大多数对象都是朝生夕灭的
- 强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡
- 跨时代引用假说:跨时代引用相对于同代引用来说仅占极少数
这两个分代假说共同奠定了多款常用的垃圾收集器的一致的设计原则;收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。显而易见,如果一个区域中大多数对象都是朝生夕灭,难以熬过垃圾收集过程的话,那么把他们集中放在一起,每次回收时只关注如果保留少量存活而不是去标记那些将要被回收的对象,就能以较低代价回收大量的空间。
注意:GC一共分为两种收集
- 部分收集(Partial GC):指目标不是完整收集收集整个Java堆的垃圾收集,其中又分为三种
- 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集
- 老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集,目前只有CMS收集器会又单独收集老年代的行为。
- 混合收集(Mixed GC):指目标收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为
- 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集