关于jvm:垃圾回收与算法

32次阅读

共计 2447 个字符,预计需要花费 7 分钟才能阅读完成。

一、如何确定垃圾

1、援用计数法
在 Java 中,援用和对象是有关联的。如果要操作对象则必须用援用进行。因而,很显然一个简略
的方法是通过援用计数来判断一个对象是否能够回收。简略说,即一个对象如果没有任何与之关
联的援用,即他们的援用计数都不为 0,则阐明对象不太可能再被用到,那么这个对象就是可回收
对象。
2、可达性剖析
为了解决援用计数法的循环援用问题,Java 应用了可达性剖析的办法。通过一系列的“GC roots”
对象作为终点搜寻。如果在“GC roots”和一个对象之间没有可达门路,则称该对象是不可达的。要 留神的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至多要通过两次标记
过程。两次标记后依然是可回收对象,则将面临回收。

GC Roots 是指:Java 虚拟机栈(栈帧中的本地变量表)中援用的对象
本地办法栈中援用的对象
办法区中常量援用的对象
办法区中类动态属性援用的对象
GC Roots 并不包含堆中对象所援用的对象,这样就不会有循环援用的问题。

二、垃圾回收算法

1.Mark-Sweep(标记 - 革除)算法
这是最根底的垃圾回收算法,之所以说它是最根底的是因为它最容易实现,思维也是最简略的。标记 - 革除算法分为两个阶段:标记阶段和革除阶段。标记阶段的工作是标记出所有须要被回收的对象,革除阶段就是回收被标记的对象所占用的空间。具体过程如下图所示:

从图中能够很容易看出标记 - 革除算法实现起来比拟容易,然而有一个比较严重的问题就是容易产生内存碎片,碎片太多可能会导致后续过程中须要为大对象调配空间时无奈找到足够的空间而提前触发新的一次垃圾收集动作。

2.Copying(复制)算法
为了解决 Mark-Sweep 算法的缺点,Copying 算法就被提了进去。它将可用内存按容量划分为大小相等的两块,每次只应用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块下面,而后再把已应用的内存空间一次清理掉,这样一来就不容易呈现内存碎片的问题。具体过程如下图所示:

这种算法尽管实现简略,运行高效且不容易产生内存碎片,然而却对内存空间的应用做出了昂扬的代价,因为可能应用的内存缩减到原来的一半。
很显然,Copying 算法的效率跟存活对象的数目多少有很大的关系,如果存活对象很多,那么 Copying 算法的效率将会大大降低。

3.Mark-Compact(标记 - 整顿)算法
为了解决 Copying 算法的缺点,充分利用内存空间,提出了 Mark-Compact 算法。该算法标记阶段和 Mark-Sweep 一样,然而在实现标记之后,它不是间接清理可回收对象,而是将存活对象都向一端挪动,而后清理掉端边界以外的内存。具体过程如下图所示:


4.Generational Collection(分代收集)算法
分代收集算法是目前大部分 JVM 的垃圾收集器采纳的算法。它的核心思想是依据对象存活的生命周期将内存划分为若干个不同的区域。个别状况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有大量对象须要被回收,而新生代的特点是每次垃圾回收时都有大量的对象须要被回收,那么就能够依据不同代的特点采取最适宜的收集算法。
目前大部分垃圾收集器对于新生代都采取 Copying 算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说须要复制的操作次数较少,然而理论中并不是依照 1:1 的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次应用 Eden 空间和其中的一块 Survivor 空间,当进行回收时,将 Eden 和 Survivor 中还存活的对象复制到另一块 Survivor 空间中,而后清理掉 Eden 和方才应用过的 Survivor 空间。
而因为老年代的特点是每次回收都只回收大量对象,个别应用的是 Mark-Compact 算法。
留神,在堆区之外还有一个代就是永恒代(Permanet Generation),它用来存储 class 类、常量、办法形容等。对永恒代的回收次要回收两局部内容:废除常量和无用的类。

三. 典型的垃圾收集器
垃圾收集算法是 内存回收的实践根底,而垃圾收集器就是内存回收的具体实现。上面介绍一下 HotSpot(JDK 7) 虚拟机提供的几种垃圾收集器,用户能够依据本人的需要组合出各个年代应用的收集器。
1.Serial/Serial Old

Serial/Serial Old 收集器是最根本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial 收集器是针对新生代的收集器,采纳的是 Copying 算法,Serial Old 收集器是针对老年代的收集器,采纳的是 Mark-Compact 算法。它的长处是实现简略高效,然而毛病是会给用户带来进展。

2.ParNew

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

3.Parallel Scavenge

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

4.Parallel Old

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

5.CMS

CMS(Current Mark Sweep)收集器是一种以获取最短回收进展工夫为指标的收集器。它是一种老年代的并发收集器,采纳的是 Mark-Sweep 算法。

6.G1

G1 收集器是当今收集器技术倒退最前沿的成绩,它是一款面向服务端利用的收集器
它能充分利用多 CPU、多核环境。因而它是一款并行与并发收集器,并且它能建设可预测的进展工夫模型。新生代和老年代都可用。

正文完
 0