Java垃圾收集器

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。

虽然我们在对各种收集器进行比较,但是并非为了跳出一个最好的收集器。因为知道现在为止还没有最好的收集器出现,更加没有万能的收集器,所以我们选择的只是对具体应用最合适的收集器。

1.Serial收集器(串行收集器)

这个收集器是一个单线程的收集器,但是它的单线程的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的线程(Stop-The-World:将用户正常工作的线程全部暂停掉),知道它收集结束。收集器的运行过程如下图所示:

上图中:

新生代采用复制算法,Stop-The-World

老年代采用标记-整理算法:Stop-The-World

当他进行GC工作的时候,虽然会造成Stop-The-World,但是它存在有存在的原因:正是因为他的简单而高效(与其他收集器的单线程比),对于限定单个CPU的环境来说,没有现成交互的开始,专心做GC,自然可以获得最高的单线程收集效率。所以Serial收集器对于运行在client模式下是一个很好的选择(它依然是虚拟机运行在client模式下的默认新生代收集器)。

2.ParNew收集器

Serial收集器的多线程版本(使用多条线程进行GC)

它是运行在server模式下的首选新生代收集器,除了Serial收集器外,目前只有它能与CMS收集器配合工作。CMS收集器是一个被认为具有时代意义的并发收集器,因此如果有一个垃圾收集器能和它配合一起使用更加完美,那这个收集器必然也是一个不可或缺的部分了。收集器的运行过程如下图所示:

上图中:

新生代采用复制算法:Stop-The-World

老年代采用标记-整理算法:Stop-The-World

3.ParNew Scanvenge收集器

类似ParNew,但更加关注吞吐量。目标是:达到一个可控制吞吐量的收集器。

停顿时间和吞吐量不可能同时调优。我们一方面希望停顿时间少,另一方面希望吞吐量高。其实这是矛盾的,因为:在GC的时候,垃圾回收的工作总量是不变的,如果将停顿时间减少,那么频率就会提高;频率提高说明会频繁的进行GC,那吞吐量就会减少,性能就会降低。

吞吐量:CPU用于用户代码的时间/CPU总消耗时间的比值。即=运行用户代码的时间/(运行用户代码时间+垃圾收集时间)。比如,虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%

4.G1收集器

是当今收集器发展的最前沿成果之一,直到JDK1.7,SUN公司才认为它达到了足够成熟的商用程度。

优点:

它最大的优点是结合了空间整合,不会产生大量的碎片,也降低了进行GC的频率。

二是可以让使用者明确指定停顿时间,(可以指定一个最小时间,超过这个时间,就不会进行回收了)

它有了这么高效率的原因之一就是:对垃圾回收进行了划分优先级的操作,这种有优先级的区域回收方式保证了它的高效率。

如果你的应用追求停顿,那G1现在已经可以作为一个可以尝试的选择,如果你的应用追求吞吐量,那G1并不会为你带来什么特别的好处。

注意:以上所有的收集器当中,当执行GC是,都会Stop-The-World,但是下面的CMS收集器却不会这样。

5.CMS收集器(老年代收集器)

CMS收集器(Concurrent Mark Sweep:并发标记清除)是一种以获取最短回收停顿时间为目标的收集器。适合应用在互联网站或者B/S系统的服务器上,这类应用尤其总是服务器的响应速度,希望系统停顿时间最短。

CMS收集器运行过程:(着重实现了标记的过程)

(1)初始标记

根可以直接关联到对象

速度快

(2)并发标记(和用户线程一起)

主要标记过程,标记全部对象

(3)重新标记

由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正。

(4)并发清除(和用户线程一起)

整个过程如下图所示:

上图中,出事标记和重新标记时,需要Stop-The-world.整个过程中号是最长的是并发标记和并发清除,这两个过程都可以和用户线程一起工作。

有点:

并发收集,低停顿。

缺点:

(1)导致用户执行速度降低。

(2)无法处理浮动垃圾,因为它采用的是标记-清除算法,有可能有些垃圾在标记之后,需要等到下一次GC才会被回收。如果CMS运行期间无法满足程序需要,那么就会临时启用Serial Old收集器来重新进行老年代的收集。

(3)由于采用的是标记-清除算法,那么就会产生大量的碎片。往往会出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前出发一次Full GC

疑问:既然标记-清除算法会造成内存空间的碎片化,CMS收集器为什么使用标记清除算法而不是标记整理算法?

答:CMS收集器更加关注停顿,它做GC的时候是和用户线程一起工作的(并发执行),如果使用标记整理算法的话,那么清理的时候就会去移动可用对象的内存空间,那么应用程序的线程就很有可能找不到应用对象在哪里。

时间: 2024-12-22 14:18:43

Java垃圾收集器的相关文章

【转】Java垃圾收集器

原文链接 http://www.cnblogs.com/gw811/archive/2012/10/19/2730258.html#top Java垃圾收集器 概述 说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史远远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当Lisp还在胚胎时期时,人们就在思考: GC需要完成的三件事情: 哪些内存需要回收? 什么时候回收? 如

Java垃圾收集器(GC)简介与最佳组合探究

Java经过近20年的演变,已经发展出一套复杂.健壮和高性能的垃圾收集器.在不同的应用场合下使用不同的GC组合能让程序性能得到可观提高.我想这也是Java这么多年来一直处于不败之地的原因之一. 以下讨论只限于Server模式下的HotSpot JVM. GC的类型 Sun/Oracle的HotSpot JVM为我们提供了多种不同的GC,一种GC只专门负责新生代或老年代的内存回收工作,所以实际使用的时候需要我们为新生代和老年代指定不同的GC.但G1例外,因为G1可以通吃整个堆内存. Serial

二、Java如何分配和回收内存?Java垃圾收集器如何工作?

线程私有的内存区域随用户线程的结束而回收,内存分配编译期已确定,内存分配和回收具有确定性.共享线程随虚拟机的启动.结束而建立和销毁,在运行期进行动态分配.垃圾收集器主要对共享内存区域(堆和方法区)进行垃圾收集回收. Java如何实现内存动态分配和内存垃圾的回收? 1.哪些内存需要回收(垃圾收集器内存回收的对象)?已经"死亡"的对象,那如何判定对象已经"死亡"了? Java堆回收的内存:已经"死亡"的对象 方法区回收的内存:废弃的常量和无用的类 2

JAVA 垃圾收集器与内存分配策略

引言 垃圾收集技术并不是Java语言首创的,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.垃圾收集技术需要考虑的三个问题是: 哪些内存需要回收 什么时候回收 如何回收 http://my.oschina.net/jiangmitiao/blog/470426 中讲到java内存运行时区域的分布,其中程序计数器,虚拟机栈,本地方法区都是随着线程而生,随线程而灭,所以这几个区域就不需要过多考虑回收问题.但是堆和方法区就不一样了,只有在程序运行期间我们才知道会创建哪

Java垃圾收集器标准详解及用途

概述 说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史远远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当Lisp还在胚胎时期时,人们就在思考: GC需要完成的三件事情:  哪些内存需要回收? 什么时候回收? 如何回收? 经过半个世纪的发展,内存的动态分配与内存回收技术已经相当成熟,一切看起来都进入了"自动化"时代,那为什么我们还要去了解GC和内存分配呢?答

Java垃圾收集器的算法

引用计数算法: Python使用的 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就是不可能再被使用的. 缺点:很难解决对象之间的相互循环引用的问题. 互相引用着对方,导致它们的计数都不为0,于是引用计数算法无法通知GC收集器回收它们. 根搜索算法: Java,C#,Lisp用的是这个. 通过一系列的名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference

Java垃圾收集器与内存分配策略

程序的计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭:栈中的栈侦随着方法的进入和退出而有条不紊地执行出栈和如栈操作. 判断对象是不是已经死亡的方法: 一.引用计数算法: 给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象是不可能再被使用的. 二.可达性分析算法: 基本思路就是通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一

java垃圾回收算法和垃圾收集器

垃圾收集算法.垃圾回收算法.java垃圾收集器 目录1. 垃圾收集算法1)引用计数法2)根搜索法2. 垃圾回收算法1)复制算法2)标记-清除算法3)标记-整理算法4)分代收集算法3. java垃圾收集器新生代GC器:1)Serial垃圾收集器2)ParNew垃圾收集器3)Parallel Scavenge垃圾收集器老年代GC器1)Serial和Parallel Scavenge都有对应的老年代版本2)CMS垃圾收集器4.java对象的内存分配位置5.java TLAB 1. 垃圾收集算法 1)引

深入理解 Java G1 垃圾收集器--转

原文地址:http://blog.jobbole.com/109170/?utm_source=hao.jobbole.com&utm_medium=relatedArticle 本文首先简单介绍了垃圾收集的常见方式,然后再分析了G1收集器的收集原理,相比其他垃圾收集器的优势,最后给出了一些调优实践. 一,什么是垃圾回收 首先,在了解G1之前,我们需要清楚的知道,垃圾回收是什么?简单的说垃圾回收就是回收内存中不再使用的对象. 垃圾回收的基本步骤 回收的步骤有2步: 查找内存中不再使用的对象 释放