并行与并发
并行:多任务同一时刻进行;多个指令在多个CPU上运行;宏观微观都是同时。
并发:多任务同一时间段进行(交替执行);多个指令在一个CPU上运行;宏观同时,微观串行。
垃圾收集器:内存回收的具体实现。
Serial
单线程:在进行垃圾收集时,必须暂停其他所有的工作线程,在用户不可见的情况下停掉用户正常工作的线程。
- 是虚拟机运行Client模式下默认的新生代收集器,没有线程交互开销,单线程效率高。
- 可以与CMS收集器配合使用。
ParNew
- Serial收集器的多线程版本,是很多运行在Server模式下虚拟机首选的新生代收集器。
- 可以与CMS收集器(老年代收集器)配合使用。
Parallel Scavenge(从废弃物中) 觅食; 捡破烂; 拾荒;
- 新生代收集器,复制算法,吞吐量优先。
- 目标:达到一个可控制的吞吐量,吞吐量就是运行用户代码的时间与CPU总消耗时间的比值。
- 停顿时间短:适合和用户频繁交互的任务。
- 高吞吐量:适合在后台运行不需要太多交互的任务。
Serial Old
- Serial的老年代版本,单线程
- 标记整理算法,主要给Client模式下的虚拟机使用
- 如果是在Server模式下:一方面与Parallel Scavenage搭配使用;另一方面可以作为CMS的后备预案。
Parallel Old
- Parallel Scavenge的老年代版本
- 多线程,标记整理算法
- Parallel Scavenge + Parallel Old 组合
CMS
- concurrent mark sweep ,为了获取最短停顿时间,由于目前很大部分Java应用集中在互联网站或B/S系统的服务端上。
过程
- 初始标记(stop the world)
标记一下GC Roots能直接关联到的对象 - 并发标记 耗时长
GC Roots tracing,判断对象是否仍在使用中,可达性分析。 - 重新标记(stop the world)
修正并发标记期间因用户程序继续运行而导致交际产生变动的那部分对象的标记记录 - 并发清除 耗时长
缺点
- 对CPU资源敏感
面向并发设计的程序都对CPU资源敏感,会导致吞吐量降低 - 无法处理浮动垃圾
程序运行不断产生新的垃圾,cms在下一次GC时清理这些垃圾。当清理垃圾时用户线程需要运行,所以还要给用户线程预留足够的空间,CMS不能像其他收集器一样,等到老年代快满了再进行收集,要预留空间。 - 标记清除算法的缺陷
G1
将整个Java堆划分为多个大小相等的Region,新生代和老年代不再是物理隔离,是一部分Region的集合。
- 面向服务端
- 分代收集
- 整体基于标记整理算法,局部基于复制算法,不会产生内存空间碎片
- 停顿可预测
G1可以有计划地避免在整个Java堆中进行全区域的垃圾收集,它跟踪各个Region里垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,优先回收价值最大的Region。 - 避免全堆扫描 Remembered Set
G1的每个Region都有个与之对应的Remembered Set,虚拟机发现程序在对Reference类型的数据进行写操作时,会产生一个 Write Barrier(屏障)暂时中断写操作,检查Reference引用的对象是否处于不同的Region中,如果是便通过CardTable把相关引用信息记录到被引用对象所属Region的Remembered Set中,回收时在GC根节点的枚举范围加入Remembered Set可以保证即使不进行全堆扫描也不会有遗漏。