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

对Java垃圾回收最大的误解是什么?它实际又是什么样的呢?

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

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

带着对性能调优指南浓厚的兴趣,咱们决定在这篇后续的博文中收集一些关于垃圾回收的流行观点,而且指出为何它们彻底是错误的。算法

来看看前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自身运行,这是不一样的两件事。ide

3. G1能解决全部问题

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

结论:没有一个奇迹般的回收器能解决全部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常见的误解?请在下面的评论区留言。

原文连接: javacodegeeks 翻译: ImportNew.com - 蒋 生武
译文连接: http://www.importnew.com/15796.html

相关文章
相关标签/搜索