Yhzhtk / note

知识代码笔记
https://github.com/Yhzhtk/note/issues
MIT License
108 stars 11 forks source link

Java 垃圾回收算法、收集器 #33

Open Yhzhtk opened 9 years ago

Yhzhtk commented 9 years ago

如何确定某个对象是“垃圾”?

引用计数法:

如果一个对象没有任何引用与之关联,则说明该对象基本不太可能在其他地方被使用。这种算法简单高效,但是它无法解决循环引用的问题。

可达性分析法:

通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

比较常见的可回收对象:

  1. 显示地将某个引用赋值为null或者将已经指向某个对象的引用指向新的对象
  2. 局部引用所指向的对象
  3. 只有弱引用与其关联的对象

    垃圾收集算法

  4. Mark-Sweep(标记-清除)算法
  5. Copying(复制)算法
  6. Mark-Compact(标记-整理)算法
  7. Generational Collection(分代收集)算法

目前大部分垃圾收集器对于新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。

而由于老年代的特点是每次回收都只回收少量对象,一般使用的是Mark-Compact算法。

注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。

垃圾收集器

Serial/Serial Old

Serial/Serial Old收集器是最基本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿。

ParNew

ParNew收集器是Serial收集器的多线程版本,使用多个线程进行垃圾收集。

Parallel Scavenge

Parallel Scavenge收集器是一个新生代的多线程收集器(并行收集器),它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量。

Parallel Old

Parallel Old是Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法。

CMS

CMS(Current Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。

G1

G1收集器是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。

参考:http://www.cnblogs.com/dolphin0520/p/3783345.html

Yhzhtk commented 9 years ago

HotSpot 虚拟机下的启动参数可以配置垃圾回收策略,分别是如下参数: (使用在启动参数,如 -XX:+ UseConcMarkSweepGC)

UseSerialGC

使用 Serial + Serial Old 组合进行回收 (Client 模型默认)

UseParNewGC

使用 ParNew + Serial Old 组合进行回收

UseParallelGC

使用 Parallel Scavenge + Serial Old 组合进行回收 (Server 模式默认)

UseParallelOldGC

使用 Parallel Scavenge + Parallel Old 组合进行回收

UseConcMarkSweepGC

使用 ParNew+ CMS + Serial Old 组合进行回收,如果 CMS 出现 Concurrent Mode Fualure,则使用 Serial Old 后备回收。