java gc --- 关键词解释
分代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的说明
java gc --- 关键词解释的更多相关文章
- 详解Java GC的工作原理+Minor GC、FullGC
详解Java GC的工作原理+Minor GC.FullGC 引用地址:http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html J ...
- 成为Java GC专家(3)—如何优化Java垃圾回收机制
为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并不总是需要进行GC优化,但前提是所运行的基于Java的系统,包含了如下参数或 ...
- Java GC 日志详解(转)
Java GC日志可以通过 +PrintGCDetails开启 以ParallelGC为例 YoungGC日志解释如下(图片源地址:这里) : FullGC(图片源地址:这里): http://blo ...
- Java GC - 监控回收行为与日志分析
1. 简介 在上一篇介绍<Java GC - 垃圾回收机制>, 本文将介绍如何监控 Javc GC 行为,同时涉及一些GUI工具的使用(虽然有些已经很老并不再更新),监控GC在于判断JVM ...
- Java GC 日志详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt105 java GC日志可以通过 +PrintGCDetails开启 以Pa ...
- jvm系列(十):如何优化Java GC「译」
本文由CrowHawk翻译,是Java GC调优的经典佳作. 本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三 ...
- Java GC性能优化实战
GC优化是必要的吗? 或者更准确地说,GC优化对Java基础服务来说是必要的吗?答案是否定的,事实上GC优化对Java基础服务来说在有些场合是可以省去的,但前提是这些正在运行的Java系统,必须包含以 ...
- JVM垃圾收集(Java Garbage Collection / Java GC)
JVM垃圾收集(Java Garbage Collection / Java GC) Java7 Java8 JDK1.8之后将最初的永久代取消了,由元空间取代. 堆内存调优简介 public sta ...
- jvm系列(七):如何优化Java GC「译」
本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的”Become a Java GC Expert”系列文章 ...
随机推荐
- python PEP8代码规范及问题
最近刚刚接触Python,为了养成好习惯,尽量保证自己写的代码符合PEP8代码规范,下面是过程中报出的警告及解决方法,英文有些翻译不太准确见谅,会不断更新: PEP 8: module level i ...
- 记忆化搜索:POJ1088-滑雪(经典的记忆化搜索)
skiing 时间限制:3000 ms | 内存限制:65535 KB 难度:5 描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑 ...
- 遗传算法 | C++版GA_TSP
嗯哼,时隔半年,再次有时间整理关于组合优化问题——旅行商问题(Traveling Salesman Problem, TSP),这次采用的是经典遗传算法(Genetic Algorithm, GA)进 ...
- 笔记-Python-cProfile
笔记-Python-cProfile 1. 简介python官方提供了cProfile和profile对程序进行性能分析,建议使用cProfile; cProfile:基于lsprof的用C语言实现的 ...
- Hive UDTF开发指南
在这篇文章中,我们将深入了解用户定义表函数(UDTF),该函数的实现是通过继承org.apache.Hadoop.hive.ql.udf.generic.GenericUDTF这个抽象通用类,UDTF ...
- Struts之准备工作
*Struts之需要准备的jar包: *Struts之xml配置文件: <?xml version="1.0" encoding="UTF-8"?> ...
- IOS开发---菜鸟学习之路--(十六)-将Image转换为Base64
我们直接在.m文件的引用头文件部分 和 @interface AddPictureViewController () 之间 加入 增加部分的代码 然后就可以使用图片转Base64了 #impor ...
- 【Palindrome Number】cpp
题目: Determine whether an integer is a palindrome. Do this without extra space. click to show spoiler ...
- fastjosn在低版本丢字段问题
简单的说: 对于java bean中有字段类似pId这种写法,特征是第一个字母小写,第二个字母大写,在eclipse中生成的getter setter方法是 getpId, setpId. 在低版本的 ...
- 【Part1】用JS写一个Blog(node + vue + mongoDB)
学习JS也有一段时间了,准备试着写一个博客项目,前后端分离开发,后端用node只提供数据接口,前端用vue-cli脚手架搭建,路由也由前端控制,数据异步交互用vue的一个插件vue-resourse来 ...