关于垃圾回收被误解的7件事

标签: 垃圾回收 | 发表时间:2015-04-27 09:55 | 作者:
出处:http://www.iteye.com
对Java垃圾回收最大的误解是什么?它实际又是什么样的呢?

当 我还是小孩的时候,父母常说如果你不好好学习,就只能去扫大街了。但他们不知道的是,清理垃圾实际上是很棒的一件事。可能这也是即使在Java的世界中, 同样有很多开发者对GC算法产生误解的原因——包括它们怎样工作、GC是如何影响程序运行和你能对它做些什么。因此我们找到了Java性能调优专家 Haim Yadid,并把名为 Java performance tuning guide的文章发表在Takipi的博客上。

最新博文:关于垃圾回收被误解的7件事
http://t.co/3QJLJuKCRqpic.twitter.com/aqQEF0zTkK
— Takipi (@takipid) April 6, 2015

带着对性能调优指南浓厚的兴趣,我们决定在这篇后续的博文中收集一些关于垃圾回收的流行观点,并且指出为什么它们完全是错误的。

来看看前7名:
1. 只有一个垃圾回收器

不,并且4也是错误的答案。HotSpot JVM一共有4个垃圾回收器: Serial, Parallel / Throughput. CMS, and the new kid on the block G1。别急,另外还有一些非标准的垃圾回收器和更大胆的实现,比如 Shenandoah或 者其他JVM使用的回收器(C4——Azul开发的无停顿回收器)。HotSpot默认使用Parallel / Throughput回收器,但它常常不是你运行程序的最佳选择。比如CMS和G1会使GC停顿(GC pause)发生的频率降低,但是对于每次停顿所花费的时间,很可能比Parallel回收器更长。另一方面来说,在使用相同大小堆内存的情况下,Parallel回收器能带来更高的吞吐量。

结论:根据你的需求(可接受的GC停顿频率和持续时间)选择合适的垃圾回收器。

2. 并行(Parallel) = 并发(Concurrent)

一个GC周期(Garbage Collection cycle)可以以STW(Stop-The-World)的形式出现,这会发生一次GC停顿,也可以并发地执行从而无需暂停应用程序。更进一步来 讲,GC算法本身可以是串行的(单线程),也可以是并行的(多线程)。因此当我们提到并发的GC时,并不代表它是并行完成的,相反当提到串行GC时,也并 不意味着就一定会出现GC停顿。在GC的世界中,并发和并行是两个完全不同的概念。并发针对的是GC周期,而并行针对GC算法自身。

结论:垃圾回收的过程实际上有两步,启动GC周期和GC自身运行,这是不同的两件事。
3. G1能解决所有问题

经过一系列修正和改 进,Java 7中引入了G1回收器,它是JVM垃圾回收器中最新的组件。G1最大的优势就是解决了CMS中常见的内存碎片问题:GC周期会从老年代(Old Generation)中释放内存块,结果内存变得像瑞士奶酪那样千疮百孔,直到JVM对其无从下手了,才不得不停下来处理这些碎片。但是故事没这么简 单,某些情况下其他回收器可能比G1有更好的表现,这完全取决于你的需求。

结论:没有一个奇迹般的回收器能解决所有GC问题,你应该通过具体实验来选择合适的回收器。
4. 平均事务时间是最需要被关注的指标

如 果你仅仅监控服务器的平均事务时间,那么很可能错过一些异常值。这些异常的情况可能对用户来说是毁灭性的,而人们没有意识到它的重要性。比如一个事务在正常情况下耗时100ms,但受到GC停顿的影响,花了1分钟才完成。除了用户没人会注意到这个问题,因为你只观察了平均事务时间。试想有1%或者更多的用 户经历了这个场景,如果只关注平均值,它就太容易被忽略了。想了解更多和延迟相关的问题和怎样正确处理,可以在 这里阅读 Gil Tene的博客。

结论:留心那些异常值,你可以知道系统最后那1%的状况。( 可不是这个1%
5. 降低新对象的分配率可以改善GC的运行状况

我们可以 粗略地把系统中的对象分为三种:长命(long-lived)对象,对它们我们一般做不了什么;中等寿命(mid-lived)对象,最大的问题可能出现在这;短命(short-lived)对象,它们的释放和回收通常都很快,在下个GC周期来临时就会消失。专注于中等寿命对象的分配率可以带来有益的结 果,这对短命和长命的对象却不是那么有效。另外,控制中等寿命对象往往是一项困难的工作。

结论:给服务器带来压力的并不单纯是对象的分配率,在运行过程中这些对象的种类才是一切麻烦的根源。

6. 调优可以解决所有事

如果你的程序需要保存大量被频繁修改的状态,对JVM堆内存进行调优就无法带来很好的收益。较长的GC停顿是不可避免的。一个解决办 法是对架构进行改善,保证一个对响应时间有决定性影响或者造成瓶颈的过程中,不包含大量状态。大量状态和响应能力是难以良好共存的,因此将它们分开处理才 是上上之选。

结论:不是所有的问题都可以通过调整JVM参数解决,有时你只需要回顾自己的绘图板。(译注:重新审视程序的设计)
7. GC日志会导致巨大的系统开销

简单来说,这是错的,尤 其在默认的日志配置下。日志数据是极为有价值的,Java 7中还引入了钩子来控制它们的大小,保证硬盘空间不被用尽。如果不收集GC日志,那么你会失去这几乎是唯一的,知晓JVM垃圾回收器在生产环境中工作状态 的方法。一般可接受的GC开销以5%作为上限,如果你能知道系统为GC停顿付出的代价,也能对最小化这个代价采取行动,这种程度的开销是不值一提的。

结论:在能力范围内,尽可能多地获取系统在生产环境中的运行数据,你会发现那是一个全新的世界。

总结

希望上面的结论能帮助你们更好地把握Java垃圾回收器的工作。在你们的程序中出现过类似问题吗?你们周围还有没有其他对GC常见的误解?请在下面的评论区留言。

本文由 ImportNew - 蒋生武 翻译自 javacodegeeks

感谢 mengyidan1988 投递这篇资讯

资讯来源: ImportNew - 蒋生武

已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [垃圾回收] 推荐:

jvm垃圾回收

- Cano - 淘宝共享数据平台 tbdata.org
在jvm中堆空间划分为三个代:年轻代(Young Generation)、年老代(Old Generation)和永久代(Permanent Generation). 年轻代和年老代是存储动态产生的对象. 永久带主要是存储的是java的类信息,包括解析得到的方法、属性、字段等等. 我们这里讨论的垃圾回收主要是针对年轻代和年老代.

JVM 垃圾回收算法

- - 码蜂笔记
《深入理解Java虚拟机:JVM高级特性与最佳实践》-笔记. 垃圾回收,Garbage Collection,简称GC. 判断对象是否存活一般有两种方式:. 引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收. 此方法简单,无法解决对象相互循环引用的问题.

Java中的垃圾回收

- - Java译站
前文中对标记删除算法的介绍更多还是偏理论性质的. 实践中,为了更好地满足现实的场景及需求,还需要对算法进行大量的调整. 举个简单的例子,我们来看下JVM需要记录哪些信息才能让我们得以安全地分配对象空间. 碎片及整理(Fragmenting and Compacting). JVM在清除不可达对象之后,还得确保它们所在的空间是可以进行复用的.

Java垃圾回收调优

- - 编程语言 - ITeye博客
在Java中,通常通讯类型的服务器对GC(Garbage Collection)比较敏感. 通常通讯服务器每秒需要处理大量进出的数据包,需要解析,分解成不同的业务逻辑对象并做相关的业务处理,这样会导致大量的临时对象被创建和回收. 同时服务器如果需要同时保存用户状态的话,又会产生很多永久的对象,比如用户session.

谈谈ActionScript垃圾回收(下)

- Tomyail - Kevin Cao&#39;s Blog
前文我们介绍了GC的工作机制和帮助GC更好工作的最佳实践. 其实只要我们遵守谁创建谁清理的原则来管理对象,就能基本上避免回收失败,也就是我们通常说的内存泄漏问题. 但是在实际项目中我们还会看到各种原因引起的内存泄漏,接下来就让我们一起来找出病因. 首先我们需要观察症状,也就是内存的使用曲线. 排查的方法是反复执行一些创建和删除对象的方法、反复加载和卸载子文件.

谈谈ActionScript垃圾回收(上)

- Jia - Kevin Cao&#39;s Blog
在《给AS程序员的一点建议一文》中我提到了释放资源的重要性. 最近在一些项目过程中我又对这方面有了更多的理解,在此希望能够分享给大家. 首先让我们来回顾一下关于垃圾回收(Garbage Collection,下文简称GC)的一些知识. 要阅读本文,你需要对GC机制有些基本认识. 在ActionScript中,我们没有API可以直接删除一个对象,也不能控制Player进行GC.

JVM垃圾回收(GC)原理

- kill - yiihsia[互联网后端技术]_yiihsia[互联网后端技术]
引用计数(Reference Counting). 原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数. 垃圾回收时,只用收集计数为0的对象. 此算法最致命的是无法处理循环引用的问题. 标记-清除(Mark-Sweep). 第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除.

HotSpot 垃圾回收算法实现

- - 码蜂笔记
《深入理解Java虚拟机:JVM高级特性与最佳实践》-笔记. 在可达性分析期间整个系统看起来就像被冻结在某个时间点上,不可以出现分析过程中对象引用关系还在不断变化的情况. 一致性要求导致GC进行时必须停顿所有Java执行线程. 即使在号称不会发生停顿的CMS收集器中,枚举根节点时也是必须停顿的. HotSpot使用的是准确式GC,当执行系统停顿下来后,并不需要一个不漏地检查完所有执行上下文和全局的引用位置,这是通过一组称为OopMap的数据结构来达到的.

Erlang进程堆垃圾回收机制

- - CSDN博客推荐文章
原文: Erlang进程堆垃圾回收机制. 作者:http://blog.csdn.net/mycwq. 每个Erlang进程创建之后都会有自己的PCB,栈,私有堆. erlang不知道他创建的进程会用到哪种场合下,所以一开始分配的内存比较小. 如果分配的空间不够了,erlang gc会动态调整堆大小以满足需求,如果分配的空间大了,就会收缩堆,回收内存.