zoukankan      html  css  js  c++  java
  • 关于垃圾回收被误解的7件事

    对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常见的误解?请在下面的评论区留言。

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

  • 相关阅读:
    Lucene in action 笔记 case study
    关于Restful Web Service的一些理解
    Lucene in action 笔记 analysis篇
    Lucene in action 笔记 index篇
    Lucene in action 笔记 term vector
    Lucene in action 笔记 search篇
    博客园开博记录
    数论(算法概述)
    DIV, IFRAME, Select, Span标签入门
    记一个较困难的SharePoint性能问题的分析和解决
  • 原文地址:https://www.cnblogs.com/digdeep/p/4461615.html
Copyright © 2011-2022 走看看