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”系列文章 ...
随机推荐
- Cyclic Nacklace HDU - 3746 (kmp)
Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- Mysql存储过程中的事务回滚
create procedure test(in a int) BEGIN ; ;-- 异常时设置为1 START TRANSACTION; ,); ,); THEN ROLLBACK; ELSE C ...
- Hive UDF开发指南
编写Apache Hive用户自定义函数(UDF)有两个不同的接口,一个非常简单,另一个...就相对复杂点. 如果你的函数读和返回都是基础数据类型(Hadoop&Hive 基本writable ...
- Android引导页过多导致OOM内存泄漏
摘要:前几天推广我们APP的时候,有些手机加载引导页的时候会闪退或崩溃,在Bugly显示是OOM异常. 然后Bugly上面显示的解决方案是: 该异常表示未能成功分配字节内存,通常是因为内存不足导 ...
- LOJ #6010. 「网络流 24 题」数字梯形
#6010. 「网络流 24 题」数字梯形 题目描述 给定一个由 n nn 行数字组成的数字梯形如下图所示.梯形的第一行有 m mm 个数字.从梯形的顶部的 m mm 个数字开始,在每个数字处可以 ...
- day23 Model 操作,Form 验证以及序列化操作
Model 操作 1创建数据库表 定制表名: 普通索引: 创建两个普通索引,这样就会生成两个索引文件 联合索引: 为了只生成一个索引文件,才 ...
- Django admin模块使用search时报错:django.core.exceptions.FieldError: Related Field got invalid lookup: contains
日志如下: <class 'django.core.handlers.wsgi.WSGIRequest'> ------------registered_admins: {'spaceCl ...
- 5、CSS基础part-3
1.CSS列表 ①类型 ul.disc {list-style-type: disc} ②位置 ul.inside {list-style-position: inside} ③列表图像 2.表格
- Hadoop架构的初略总结(1)
Hadoop架构的初略总结(1) Hadoop是一个开源的分布式系统基础架构,此架构可以帮助用户可以在不了解分布式底层细节的情况下开发分布式程序. 首先我们要理清楚几个问题. 1.我们为什么需要Had ...
- Fragment控件初始化
代码改变世界 Fragment控件初始化 @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup ...