`
mshijie
  • 浏览: 96116 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

简单理解耗时的Java GC

阅读更多

参考地址:

http://www.cloudera.com/blog/2011/02/avoiding-full-gcs-in-hbase-with-memstore-local-allocation-buffers-part-1/

java GC工作在分代的模型上。大多数的对象要么很快的死亡,要么持续较长的时间。例如,方法栈中创建的对象只会持续几毫秒时间,而缓存中的对象会持续几分钟。

既然对象有两种不同的什么周期,直觉认为,使用不同的垃圾收集算法也许能够在不同的周期中更好的完成工作。所以,JVM把堆空间拆封为两个不同的区域,新生代,旧生代。当对象刚开始创建的时候,会被分配到新生代。当对象在新生代中经过多次gc后,依然存活时,就假设这个对象将持续较长时间,就把这个对象复制到旧生代中去。

JVM加上启动参数-XX:+UseParNewGC 和 -XX:+UseConcMarkSweepGC将为新生代启用Parallel New collector为旧生代启用Concurrent Mark-Sweep collector。

Parallel New collector工作时,会首先停止所有运行中的java线程。然后追踪对象引用以判断哪些对象是活着的。最后把活着的对象复制到一个一块空闲的堆区域,更所所有的指针到新的地址。有两个重要地方值得注意

  1. 它会暂停所有线程,但时间非常短暂。因为新生代通常非常的小,而且是多线程收集的。它能够非常快的完成工作。生产环境中,通常建议新生代设置不超过512M,这样最坏的暂停时间也不会超过几百毫秒。
  2. 收集时,复制所有存活的对象到一块连续的空闲堆空间中去,这块空间叫做S1,S2,交替使用。如果S1或者S2空间不够使,剩下的存活对象会被复制到旧生代中区。

每次复制一个对象后,将增加这个对象的收集计数,当一个对象在新生代中被复制了一定次数后,该算法即判定该对象是长周期的对象,把他移动到旧生代。这个阈值叫着tenuring threshold。

旧生代的Concurrent Mark Sweep(CMS)

每次Parallel New collector工作时,会把一部分对象复制到旧生代中。所以,旧生代很快就会被填满,就需要一个策略来收集它。CMS负责处理旧生代中的死亡对象。

CMS通过多个步骤来完成工作。有一些步骤会暂停所有线程(stop the world),其他步骤是和应用并行的执行的。主要的步骤为:

  1. 初始标记(stop the world)。在这个步骤中,CMS放置一个标记在所有root对象中。一个root对象是被当前线程直接引用的对象,例如,线程当前使用的本地变量。这个步骤会很快完成,因为root对象是非常少的。
  2. 并行标记。收集器开始跟随并标记所有root对象的引用,直到标记完所有的引用,即存活的对象。
  3. 再次标记(stop the world)。在并行标记的过程中,有一些对象引用可以已经变化了,也有一些新的对象被创建。需要把这些变化考虑在内。这个步骤也非常的短暂,因为CMS使用一个特殊的数据结构,只处理这期间的修改
  4. 并行回收。所有没有被标记的对象,都将被删除,释放内存空间。在这个步骤中新创建的对象,会被直接标记,以免被删除。

有几个重要地方需要注意:

  1. stop the world的时间,是短暂的。所有扫描整个heap和删除的操作都是并行执行的。
  2. CMS收集器,不会移动压缩存活对象。所以空闲空间是分散在整个heap中的,会存在很多的碎片。

如上面描述,CMS收集器工作得很好,只暂停很短的时间,大多数耗时操作都是并行执行的。但运行中几分钟的长时间暂停是怎么产生的?是因为,CMS有两个特殊的失败情况需要处理。

第一种失败,Concurrent Mode Failure,经常讨论的一种失败。假如我们有个8GB的堆空间,其中已使用了7GB。CMS将开始它的第一步操作。在这个时候,更多的对象被创建并转移到旧生代中,如果转移速度太快,旧生代将在CMS标记完所有对象前被填满。因为没有更多的空间可供使用,应用程序将无法继续执行。CMS不得不暂停并行标记,并暂停所有的线程,使用单线程的复制算法,把所有堆空间的存活对象复制到堆的开始,然后回收内存空间,在这个长时间的暂停后,程序才能继续执行。这种情况看起来应该很容易避免,我们只需要让CMS在内存空间不够前完成工作。可以通过参数-XX:CMSInitiatingOccupancyFraction=N,来配置CMS开始工作的时机,N已使用的堆空间百分比。

第二种失败是因为空间碎片。CMS不会重新分配存活的对象,所以堆中的空闲空间将是分散的。例如,我们分配100W的对象,每个对象占用空间1KB,消耗了所有的堆空间,然后回收所有的偶数对象,剩下50W的对象,占用500M内存空间,还剩余500M内存空间,但是剩余空间是50W个1KB的不连续的快,如果这个时候,需要分配一个2KB的对象,将没有可用的空间供其分配。在这种情况下,CMS也不得不暂停所有线程,压缩堆空间。

所以,耗时的gc时间,主要是因为CMS两者异常工作方式产生的。应用程序设计中就需要考虑如何避免这两情况的产生,从而减少full gc暂停对应用产生的致命影响


 

分享到:
评论

相关推荐

    Java GC 专题

    Java垃圾收集(GC)专题针对的是Java编程语言中内存管理机制的重要组成部分。Java自1996年推出以来,其最大的改进之一就是引入了受管内存。在Java之前,C和C++语言中的内存泄漏问题十分常见,这导致开发稳定和安全的...

    Java基础[Java基础]--Java GC工作原理

    通过对GC原理的理解和合理配置,开发者可以有效地管理Java应用的内存使用,提高应用的性能和稳定性。无论是增量式GC还是分代收集策略,都是为了更好地适应不同应用场景的需求,实现最优的内存管理方案。

    gcviewer监控gc工具

    《GCViewer:深入理解Java垃圾收集日志分析与监控》 在Java开发中,内存管理和垃圾收集是至关重要的环节,不当的内存管理可能导致系统性能下降甚至出现应用崩溃。GCViewer是一款强大的工具,专用于分析和监控Java...

    Java VisualVM gc工具

    这款工具集成了多种功能,包括内存分析、线程分析、CPU剖析、JVM配置信息查看等,其中GC(Garbage Collection)插件是其重要的组成部分,用于帮助开发者深入理解Java应用程序的垃圾回收机制。 垃圾回收是Java虚拟机...

    java jstat 查看哪个进程频繁GC垃圾回收

    总的来说,通过`jstat`和GC日志,我们可以深入理解Java进程的内存行为,定位并解决频繁GC的问题,从而提高应用性能。记住,优化JVM配置是一项细致的工作,需要根据具体应用的特性进行调整,不能一概而论。

    java jvm-old gc耗时几十s,导致系统告警(csdn)————程序.pdf

    总结来说,解决Java应用中old GC耗时过长的问题,需要深入理解应用的内存使用模式,合理调整JVM参数,选择合适的垃圾收集器,并进行持续的性能监控和调优。在调整过程中,应遵循最小化停顿时间、最大化吞吐量和优化...

    GCViewer-FullGC分析工具

    总结来说,GCViewer是一款强大的Java Full GC分析工具,它通过图形化界面使复杂的GC日志变得易于理解和分析。通过深入理解GCViewer的功能和使用方法,开发者能够更好地诊断和优化Java应用程序的内存性能,提升整体...

    java虚拟机中gc的基本原理 .docx

    理解GC的基本原理对于优化Java应用的性能至关重要,尤其是在对性能要求较高的场景,如嵌入式系统和实时系统。 GC的基本原理主要涉及到对象的生命周期管理和内存的自动回收。当程序员通过`new`关键字创建一个对象时...

    visualVM插件包Branch GC等

    VisualVM可以显示不同GC策略下的内存分配和回收情况,包括新生代、老年代的内存使用情况,GC事件的发生频率、耗时等。这对于调优Java应用程序的内存设置非常有帮助。 4. **GC插件** "Branch GC等"可能指的是...

    gcviewer-1.35-SNAPSHOT

    GCViewer以图形化的方式展示各种GC指标,如GC次数、总耗时、每次GC的平均时间等。这些图表包括直方图、折线图和堆栈图,便于用户从不同角度理解GC行为。 4. **多视图分析**: 工具提供了多种视图,包括年轻代、老...

    VisualGC.zip

    2. **GC日志视图**:记录每次GC事件的详细信息,如GC类型、耗时、内存变化等。这对于分析GC性能和调优策略至关重要。 3. **对象视图**:展示不同类型的对象数量及其占用的内存,有助于识别可能的内存泄漏问题。 4....

    gcviewer134.zip

    3. **详细统计**:GCViewer提供详细的统计信息,包括每次GC的耗时、回收的内存量、新生代和老年代的变化趋势等,这些信息对于理解内存行为非常有帮助。 4. **对比分析**:用户可以导入多个GC日志进行对比,以便于在...

    com-sun-tools-visualvm-modules-visualgc.zip

    《深入理解Java虚拟机:VisualVM与VisualGC插件详解》 在Java开发过程中,对内存管理和垃圾收集(Garbage Collection,简称GC)的理解与优化是至关重要的。VisualVM是一款强大的Java性能分析工具,它提供了丰富的...

    Java中GC的工作原理详细介绍

    Java的垃圾回收(GC)机制是其...理解并优化GC机制是提升Java程序性能的关键,尤其是在资源有限或对响应时间有严格要求的系统中。通过深入学习和实践,开发者可以更好地掌控GC的行为,编写出更加高效和稳定的Java应用。

    VisualGC 内存监控工具

    VisualGC作为JVM(Java虚拟机)内存监控的插件,为开发者提供了直观且详尽的内存使用情况,帮助我们理解和解决内存泄漏、垃圾收集等问题。本文将深入探讨VisualGC的使用及其在JDK1.8中的应用。 首先,VisualGC是...

    visualgc.rar

    《深入理解Java 8垃圾收集与VisualVM插件VisualGC》 在Java编程领域,内存管理和垃圾收集(Garbage Collection, GC)是至关重要的部分,它确保了程序的高效运行和内存的有效利用。随着Java 8的发布,其在垃圾收集...

    Visual GC(监控垃圾回收器)

    《Visual GC:深入理解Java应用程序性能优化》 Visual GC,是Java开发中一款不可或缺的利器,它是VisualVM工具的一部分,提供了强大的垃圾回收监控功能。VisualVM是一款由Oracle公司开发的多合一工具,它集成了诸如...

    Java理解Throughput收集器.pdf

    《Java理解Throughput收集器》 在Java虚拟机(JVM)中,垃圾收集器是内存管理的关键组成部分,负责自动回收不再使用的对象所占用的内存空间。本文主要讨论的是Throughput收集器,这是一种专注于提高应用程序总体...

    VisualGC(监控程序性能调优)

    通过VisualGC,你可以观察到不同GC算法(如Serial、Parallel、CMS、G1等)下的GC活动,包括GC事件的发生频率、耗时、内存区域的变化等。 VisualVM还提供了以下关键功能: 1. **线程分析**:查看并分析应用程序中的...

Global site tag (gtag.js) - Google Analytics