Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来。
关于垃圾收集(Garbage Collection,GC),先思考三个问题:
- 哪些内存需要回收?
- 什么时候回收?
- 如何回收?
上一篇讲过的Java内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈这3个区域随线程而生,随线程而灭,所以这几个区域不用过多考虑回收的问题。而Java堆和方法区不一样,这部分内存的分配和回收都是动态的,垃圾回收器关注的是这部分的内存,接下来讨论的“内存”分配和回收也仅指这一部分内存。
对象存活判定算法——可达性分析算法
利用可达性能分析算法判定对象是否存活。
垃圾收集算法
1. 标记-清除(Mark-Sweep)算法
它主要有两点不足:(a)效率问题,标记和清除两个过程的效率都不高;(b)空间问题,标记清除之后会产生大量不连续的内存碎片。
2. 复制算法
现在的商业虚拟机都采用这种收集算法来回收新生代。老年代一般不能直接选用该算法。
HotSpot虚拟机默认Eden与Survivor的大小比例是8:1。
当Survivor空间不够用时,需要依赖其他内存(老年代)进行分配担保(Handle Promotion)。
3. 标记-整理算法
相对于标记-清除算法来说,标记过程一样,但是后续步骤不是对可回收对象直接进行清理,而是让所有存活对象都向一端移动,然后直接清理掉边界以外的内存,可避免产生大量不连续的内存碎片。
4. 分代收集算法
根据对象存活周期的不同将内存划分为几块,一般是将Java堆划分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
垃圾回收器
收集算法是内存回收的方法论,垃圾收集器是内存回收的具体实现。
本文介绍的收集器是基于JDK 1.7 Update 14之后的HotSpot虚拟机。
1. Serial收集器
Serial收集器是最基本,发展历史最悠久的收集器。它是一个单线程的收集器,即它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是,在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束(Stop The World)。
Serial收集器到现在为止,依然是虚拟机运行在Client模式下的默认新生代收集器。
2. ParNew收集器
ParNew收集器其实就是Serial收集器的多线程版本。除了多线程收集之外,其他与Serial收集器并无太多创新之处。它是运行在Server模式下的虚拟机中首选的新生代收集器,一种有一个与性能无关但很重要的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作。
- 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程任然处于等待状态。
- 并发(Concurrent):指用户线程与垃圾收集线程同时进行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行在另一个CPU上。
3. Parallel Scavenge收集器
Parallel Scavenge收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。
这个收集器的特点是它的关注点和其他收集器不同,CMS等收集器的关注点是尽可能的缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标是达到一个可控的吞吐量(Throughput)。
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
停顿时间越短越适合需要与用户交互的程序,而高吞吐量则可以高效率的利用CPU的时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。
还有一点,它具有自适应调节策略,Parallel Scavenge收集器有一个参数-XX:+UseAdaptiveSizePolicy,虚拟机会自己动态调整一些参数以提供最适合的停顿时间和最大吞吐量。
4. Serial Old收集器
是Serial收集器的老年代版本,单线程,使用“标记-整理”算法。主要意义也是在于给Client模式下的虚拟机使用。还是作为CMS收集器的后背预案。
5. Parallel Old收集器
是Parallel Scavenge收集器的老年代版本,它们组成了“吞吐量优先”收集器的应用组合,多线程,使用“标记-整理”算法。
6. CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获得最短回收停顿时间为目标的收集器。它是基于“标记-清除”算法实现的。整个过程分为4个步骤:
- 初始标记 (Stop The World &时间短)
- 并发标记 (耗时最长)
- 重新标记 (Stop The World &时间稍长,比初始标记长,但远比并发标记时间短)
- 并发清除
优点:并发收集、低停顿
缺点:
a. 对CPU资源非常敏感
b. 无法处理浮动垃圾
c. 基于“标记-清除”算法,会有大量空间碎片产生。
7. G1收集器
当前收集器技术发展的最前沿成果之一。是一款面向服务端应用的垃圾收集器。它的特点:
a. 并行与并发
b. 分代收集
c. 空间整合
d. 可预测的停顿
内存分配与回收策略
下面是基于Serial/Serial Old收集器下的内存分配和回收策略
- 对象优先在Eden分配
- 大对象直接进入老年代
- 长期存活的对象将进入老年代
- 动态对象年龄判定
- 空间分配担保