分代gc

java的堆内存主要分为young generation与old generation,这两块分开回收。这就是所谓的分代gc

其中young generation又分为一个eden space与两个survivor space(From与To)。默认情况下,eden space占young generation的80%,两个survivor space各占10%。

young gc:新对象一般在eden space中分配,如果eden space满了,就进行一次。eden space + From 中的所有存活对象会被复制到To里去(这是因为大部分的新分配对象都会迅速死亡,每个survivor space虽然只占young generation的10%,但是一般情况下足够存放young gc中的存活元素)。每次young gc之后,From与To交换。

每个Object的对象头里都有字段用于记录这个对象经历了多少次young gc。如果一个对象熬过了一定次数(可以通过-XX:MaxTenuringThreshold配置,默认为15次)的Young gc而不死,那么可以晋升到old generation。

如果新对象的体积过大(可以通过-XX:PretenureSizeThreshold配置,但是该设置只对Serial和ParNew收集器生效),那么它会被直接分配到old generation

full gc:如果old generation也满了,就会触发full gc。full gc会对整个堆空间做gc。具体的操作是从gc root(下文介绍)出发,遍历所有可达对象,然后回收所有不可达对象。正常情况下会回收大量的内存,如果full gc后还是无法获得足够分配对象的内存,就会抛出OOM错误。

一般来说young gc的耗时较少(数十或者数百毫秒级别),full gc耗时较长(一般在秒级别,如果堆内存很大,甚至可以产生分钟级别的停顿)

gc root

gc的起点,一组可以保证绝对存活的对象,例如:

Class - 由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。我们需要注意的一点就是,通过用户自定义的类加载器加载的类,除非相应的java.lang.Class实例以其它的某种(或多种)方式成为roots,否则它们并不是roots,.
Thread - 活着的线程
Stack Local - Java方法的local变量或参数
JNI Local - JNI方法的local变量或参数
JNI Global - 全局JNI引用
Monitor Used - 用于同步的监控对象
Held by JVM - 用于JVM特殊目的由GC保留的对象,但实际上这个与JVM的实现是有关的。可能已知的一些类型是:系统类加载器、一些JVM知道的重要的异常类、一些用于处理异常的预分配对象以及一些自定义的类加载器等。然而,JVM并没有为这些对象提供其它的信息,因此就只有留给分析分员去确定哪些是属于"JVM持有"的了。

remember set/card table/write barrier

重新考虑上文提到的young gc,我们怎样才能知道young gen中的哪些对象是可达的?

最朴素的思想当然是从gc root出发,对整个heap中的对象进行可达性分析。这毫无疑问可以解决问题,但是如果这样做,young gc和full gc又有什么区别呢?

所以我们需要额外的机制来记录,old gen中的哪些对象引用了young gen中的对象。也可以理解为扩充了young gc中gc root的范围。

Remembered Set是在实现部分垃圾收集(partial GC)时用于记录从非收集部分指向收集部分的指针的集合的抽象数据结构。

card table是remember set的一种实现,card table实际上是一个byte数组,card table中的每个byte(也就是所谓的card)都对应了old gen中的一小块内存(chunk,默认是512byte)。如果card table中的某个card被标记为dirty,那么这个card对应的chunk中可能存在指向young gen的对象。在young gc时,就只需要扫描gc root + old gen中的dirty chunk中的对象即可。

card table的维护是由write barrier来完成的。任何对old gen中对象的修改,都会导致这个对象所在的chunk对应的card被标记为dirty。

card table的维护会带来一定的开销,但是根据统计分析,它确实可以极大的减少young gc的开销,所以还是值得的。

stw

stop the world,顾名思义,jvm中的所有工作线程都会暂停。此时整个java进程处于无响应状态。

young gc与full gc都会引起stw,只是时间长短的区别

promotion guarantee check

本节的讨论基于CMS算法

每次Minor GC执行完以后,虚拟机会检查之前晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则发起一次Full/Major GC,如果小于,则查看HandlePromotionFailure值是否允许担保失败,如果允许,那只会进行一次Minor GC。如果不允许失败,那么也要改为进行一次Full/Major GC

如果young gc时,To的空间不足以存放From + Eden中的存活对象,那么这些对象会被直接移动到old gen中(即使它们的年龄还不足以提升到old gen,这个情况叫做premature promotion,中文大概叫“过早提升”,它会导致full gc频率提高,jvm虽然尽力优化,但还是无法避免)。如果此时old gen的空间也不足,就会引发Promtion failed。Promtion failed会引发full gc。

concurrent mode failure

Concurrent Mode Failure
The CMS collector uses one or more garbage collector threads that run simultaneously with the application threads with the goal of completing the collection of the tenured generation before it becomes full. As described previously, in normal operation, the CMS collector does most of its tracing and sweeping work with the application threads still running, so only brief pauses are seen by the application threads. However, if the CMS collector is unable to finish reclaiming the unreachable objects before the tenured generation fills up, or if an allocation cannot be satisfied with the available free space blocks in the tenured generation, then the application is paused and the collection is completed with all the application threads stopped. The inability to complete a collection concurrently is referred to as concurrent mode failure and indicates the need to adjust the CMS collector parameters. If a concurrent collection is interrupted by an explicit garbage collection (System.gc()) or for a garbage collection needed to provide information for diagnostic tools, then a concurrent mode interruption is reported.

1. 如果old gen在被用完前不能完成对无引用对象的回收。

2. 如果old gen中的剩余空间不能满足应用的内存分配需求。

上面这两个场景会引发Concurrent Mode Failure,此时old gen的收集器会从CMS切换到Serial Old,这会引起一次有非常长的stw的full gc

参考资料

http://hllvm.group.iteye.com/group/topic/21468#post-272070   RednaxelaFX对card table的说明

http://blog-archive.griddynamics.com/2011/06/understanding-gc-pauses-in-jvm-hotspots.html   card table + 分代gc

https://blogs.msdn.microsoft.com/abhinaba/2009/03/02/back-to-basics-generational-garbage-collection/   微软对card table的说明

http://dept.cs.williams.edu/~freund/cs434/hotspot-gc.pdf  card table + 分代gc

https://www.yourkit.com/docs/java/help/gc_roots.jsp  gc root都有什么?

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html  oracle官方的gc调优文档

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html   oracle官方对cms的说明

转载于:https://www.cnblogs.com/stevenczp/p/6595995.html

java gc --- 关键词解释相关推荐

  1. java同步关键词解释、synchronized、线程锁(Lock)

    1.java同步关键词解释 21.1 synchronized synchronized是用来实现线程同步的!!! 加同步格式: synchronized( 需要一个任意的对象(锁) ){ 代码块中放 ...

  2. Java GC 日志详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt105 java GC日志可以通过 +PrintGCDetails开启 以Pa ...

  3. jvm 系列(九):如何优化 Java GC 「译」

    本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的"Become a Java GC Expert ...

  4. jvm系列(十):如何优化Java GC「译」

    本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的"Become a Java GC Expert ...

  5. 成为Java GC专家(5)—Java性能调优原则

    2019独角兽企业重金招聘Python工程师标准>>> 这是"成为Java GC专家"系列的第五篇文章.在第一篇深入浅出Java垃圾回收机制中,我们已经学习了不同 ...

  6. 深入理解JVM(4)——如何优化Java GC「译」

    本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三篇<How to Tune Java Garbage C ...

  7. jvm系列(九):如何优化Java GC「译

    本文由CrowHawk(https://crowhawk.github.io/2017/08/21/jvm_4/)翻译,是Java GC调优的经典佳作. 本文翻译自Sangmin Lee发表在Cubr ...

  8. Java GC系列(1):Java垃圾回收简介

    转载自  Java GC系列(1):Java垃圾回收简介 这篇教程是系列第一部分.首先会解释基本的术语,比如JDK.JVM.JRE和HotSpotVM.接着会介绍JVM结构和Java 堆内存结构.理解 ...

  9. jvm系列(九):如何优化Java GC

    转载自 jvm系列(九):如何优化Java GC「译」 本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三篇&l ...

最新文章

  1. 关于异常的处理的总结
  2. 错误解决记录------------mysql连接本地数据库显示can't get hostname for your address
  3. zoj3195 联通树上三个点的路径长
  4. spss 22 0统计分析从入门到精通_「转需」20+统计分析软件使用工具包,一次全搞定...
  5. 近100个Spring/SpringBoot常用注解汇总!
  6. 计算机网络之传输层:4、TCP连接管理
  7. 【前排选手分享】初赛尾声将至,大神带你最后一搏!
  8. Wagtail Usage guide:Wagtail 使用指南
  9. 孤军奋战的百合网 下一城会在哪?
  10. 向量的点乘(内积、数量积)和叉乘(外积、向量积)
  11. 修改android模拟器位置
  12. [转]一个计算机高手的成长
  13. 【系统篇 / 域】❀ 06. Windows10 加入域 ❀ Windows Server 2016
  14. 文字识别(一)--传统方案综述
  15. 初学者の发送QQ邮箱完整代码
  16. 《寂静岭》完全资料手册
  17. PA-1190201215-冯开来(计算机系统大作业)
  18. HIT 2019春软件构造Lab1
  19. 马尔奖得主 Alan Yuille | AI 视觉的未来:像人一样看世界
  20. 信息系统开发与管理【三】之 系统开发方法概述

热门文章

  1. 反病毒引擎设计全解(一)
  2. 新手学习DaVinci笔记一:查找资料篇
  3. java transient关键字
  4. 一文看懂Python(五)-----文件篇
  5. Linux下实现USB口的热插拔
  6. ubuntu下和开发板下播放音乐
  7. 1041 Be Unique
  8. 一文看懂Transformer内部原理(含PyTorch实现)
  9. PoW 本质上是个去中心化的时钟
  10. gRPC学习记录(六)--客户端连接池