文章目录
HotSpot虚拟机的垃圾收集器 ,如果两个收集器之间存在连线,就说明它们可以搭配使用;
注意:新生代的垃圾回收器 都是复制算法,老年代都是“标记-清理”或者“标记-整理”算法。
新生代的垃圾回收器 都是复制算法
新生代的垃圾回收器 都是复制算法
新生代的垃圾回收器 都是复制算法
3.5.1 Serial收集器
serial
n.电视连续剧;广播连续剧;杂志连载小说
adj.顺序排列的;排成系列的;连续的;多次的;以连续剧形式播出的;连载的
特点
- 新生代垃圾收集器
- 使用复制算法
- 单线程垃圾收集,并且其进行垃圾收集时,必须暂停所有工作线程;即会"Stop The World";
- 能与CMS收集器配合工作
注意:随着垃圾收集器的不断发展,用户线程的停顿时间在不断缩短,但是仍然没有办法完全消除(这里暂不包括RTSJ中的收集器)。
serial收集器,parNew收集器,CMS收集器三者都关注尽可能缩短垃圾收集时用户线程的停顿时间。
应用场景
是Hot Spot在Client模式下默认的新生代收集器;
也有优于其他收集器的地方:
- 简单高效(与其他收集器的单线程相比);
- 对于限定单个CPU的环境来说,Serial收集器没有线程交互(切换)开销,可以获得最高的单线程收集效率;
3.5.2 ParNew收集器
特点
- 新生代垃圾收集器
- 使用复制算法
- 多线程收集器(Serial收集器的多线程版本,但是也会GC停顿)
- 能与CMS收集器配合工作
能与CMS收集器配合工作
目标,serial收集器,parNew收集器,CMS收集器 三者都关注尽可能缩短垃圾收集时用户线程的停顿时间。
ParNew收集器除了是多线程,其余和Serial收集器基本一样
在单个CPU环境中,不会比Serail收集器有更好的效果,因为存在线程交互开销。
serial收集器,parNew收集器,CMS收集器 三者都关注尽可能缩短垃圾收集时用户线程的停顿时间。
3.5.3 Parallel Scavenge收集器
parallel 平行的;极相似的;同时发生的;相应的;对应的;并行的
scavenge 捡破烂
特点
- 新生代垃圾收集器
- 使用复制算法
- 多线程收集器
Parallel Scavenge收集器目的:达到可控制的吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间));这点与其它垃圾收集器不同,其它垃圾收集器目的是缩短垃圾收集时用户线程停顿时间;
(了解)自适应调节策略也是Parallel Scavenge收集器与ParNew收集器的一个重要区别。
3.5.4 Serial Old 收集器
Serial收集器的老年代版本,单线程收集器,使用标记-整理算法;
3.5.5 Parallel Old收集器
Parallel Old是Paraller Seavenge收集器的老年代版本,多线程收集器,使用标记-整理算法;
3.5.6 CMS收集器(重要)
Concurrent Mark Sweep
sweep
v.扫; 打扫; 清扫; 扫去; 清除; (迅猛地)推送,吹走,冲走,带走;
n. 扫; 打扫; 清扫; 挥动; 掠; (道路、河流、海岸等)一长段,绵延弯曲的地带,呈缓坡状的地带;concurrent
adj.并存的;同时发生的
- 以获取最短收集停顿为目标
- 基于 标记-清除 算法
serial收集器,parNew收集器,CMS收集器三者都关注尽可能缩短垃圾收集时用户线程的停顿时间。
运作过程分为4步:
初始标记
独占CPU,仅标记GC roots能直接关联的对象,速度快;并发标记
进行GC Roots的Tracing过程,可以和用户线程并行执行,标记所有可达对象;重新标记
独占CPU,修正 ++并发标记++ 期间 因 用户程序运作而产生标记变动的对象 的记录;并发清除
清理垃圾,可以和用户线程并行执行;
++初始标记++和++重新标记++仍然需要“Stop The World”;
优点
并发收集、低停顿
缺点
-
CMS收集器对CPU资源非常敏感,CMS默认启动的回收线程数是(CPU数量+3)/4,
-
CMS收集器无法处理浮动垃圾,可能出现"Concurrent Mode Failure"失败而导致另一次Full GC产生。
浮动垃圾:在最后一步的++并发清理++过程中,一起运行着的用户线程也会产生垃圾,但是这部分垃圾是在标记之后,所以只有等到下一次gc的时候清理掉,这部分垃圾叫浮动垃圾;
正是因为并发标记和并发清除线程都与用户线程一起跑的,那么就需要预留内存给用户线程使用,如果预留的内存不够就会出现"Concurrent Mode Failure";
- CMS是基于标记-清除算法实现的,会产生大量的空间碎片.
为了解决大量的空间碎片这个问题CMS提供了一个开关参数,用于在CMS顶不住,要进行Full GC时开启内存碎片的合并整理过程,但是内存整理的过程是无法并发的,空间碎片没有了但是停顿时间变长了.
3.5.7 G1收集器(非常重要)
G1收集器的运作步骤:
- 初始标记(Initail Marking)
仅标记GC roots能直接关联的对象,速度快;
- 并发标记(Concurrent Marking)
并发标记阶段是从GC Root开始 对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执 行。
- 最终标记(Final Marking)
最终标记阶段则是为了修正在++并发标记++期间因用户程序继续运作而导致标记产生变动 的那一部分标记记录;
- 筛选回收(Live Data Counting and Evacuation)
最后在筛选回收阶段首先对各个Region的回收价值和成本进行排序, 根据用户所期望的GC停顿时间来制定回收计划
G1将整个java堆划分为多个大小相等的区域(Regoin);
G1跟踪每个region里的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需要时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先收集价值最大的region,这种使用region划分空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获得尽可能高的收集率。
特点:
- 并行与并发;
- 分代收集;
- 不像其它垃圾收集器,G1可以独立管理整个GC堆;
- 空间整合;
整体上是基于“标记-整理”算法,局部上是基于“复制”算法实现; - 可预测的停顿;
在G1收集器中,Region之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用,虚拟机都是使用Remembered Set来避免全堆扫描的。
G1中每个Region都有一个与之对应的Remembered Set。
3.5.8 理解GC日志
vm运行参数
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+PrintHeapAtGC
-Xms20M -Xmx20M -Xmn10M 这3个参数限制了Java堆大小为20MB,不可扩展,其中10MB分配给新生代,剩下的10MB分配给老年代。
-XX:SurvivorRatio=8 定义了新生代中Eden区与一个Survivor区的空间比例是8:1,
-XX:+PrintGCDateStamps打印Gc时间
-XX:+PrintGCDetails打印Gc细节(只要这一个参数也可以)
测试
public class GCLogDemo {
public static void main(String[] args) throws InterruptedException {
byte [] b = new byte[i*1024*1024];//1m的对象
}
}
Heap
PSYoungGen total 9216K, used 2891K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 35% used [0x00000000ff600000,0x00000000ff8d2fc0,0x00000000ffe00000)
from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
ParOldGen total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000)
Metaspace used 3217K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 348K, capacity 388K, committed 512K, reserved 1048576K
可以看出
eden大约剩余8M,用了2M,其中1M左右是JVM自己的对象,1M是数组b;
eden space 8192K, 35% used
form和to都有1M可用,并没有被使用
from space 1024K, 0% used
to space 1024K, 0% used
ParOldGen total 10240K, used 0K老年代10M