转自CSDN

上一篇总结GC的基础算法,各种GC收集器的基本原理,还是比较粗粒度的概念。这篇会整理一些GC的常见概念,理解了这些概念,相信对GC有更加深入的理解

1. 什么时候会触发Minor GC?

  • Eden区域满了,或者新创建的对象大小 > Eden所剩空间
  • CMS设置了CMSScavengeBeforeRemark参数,这样在CMS的Remark之前会先做一次Minor GC来清理新生代,加速之后的Remark的速度。这样整体的stop-the world时间反而断
  • Full GC的时候会先触发Minor GC

2. 什么时候会触发Full GC?

  • Minor GC后存活的对象晋升到老年代时由于悲观策略的原因,有两种情况会触发Full GC, 1种是之前每次晋升的对象的平均大小 > 老年代剩余空间
  • 1种是Minor GC后存活的对象超过了老年代剩余空间。这两种情况都是因为老年代会为新生代对象的晋升提供担保,而每次晋升的对象的大小是无法预测的,所以只能基于统计,1个是基于历史平均水平,一个是基于下一次可能要晋升的最大水平。这两种情况都是属于promotion failure
  • CMS失败,发生concurrent mode failure会引起Full GC,这种情况下会使用Serial Old收集器,是单线程的,对GC的影响很大。concurrent mode failure产生的原因是老年代剩余的空间不够,导致了和gc线程并发执行的用户线程创建的大对象(由PretenureSizeThreshold控制新生代直接晋升老年代的对象size阀值)不能进入到老年代,只要stop the world来暂停用户线程,执行GC清理。可以通过设置CMSInitiatingOccupancyFraction预留合适的CMS执行时剩余的空间
  • 新生代直接晋升到老年代的大对象超过了老年代的剩余空间,引发Full GC。注意于promotion failure的区别,promotion failure指的是Minor GC后发生的担保失败
  • Perm永久代空间不足会触发Full GC,可以让CMS清理永久代的空间。设置CMSClassUnloadingEnabled即可
  • System.gc()引起的Full GC,可以设置DisableExplicitGC来禁止调用System.gc引发Full GC

3. CMS不等于Full GC,很多人会认为CMS肯定会引发Minor GC。CMS是针对老年代的GC策略,原则上它不会去清理新生代,只有设置CMSScavengeBeforeRemark优化时,或者是concurrent mode failure的时候才会去做Minor GC

4. 什么情况下新生代对象会晋升到老年代?

  • 当对象大小超过了PretenureSizeThreshold设置的对象大小阀值时,对象直接在老年代分配空间
  • 当age从1开始的对象大小累计超过了Survivor区域的1/2(TargetSurvivorRatio所定义)时,会计算一个Thenuring Threshold,超过这个年龄的新生代对象会进入到老年代,即使这时候新生代还有很多的空间。注意MaxTenuringThreshold只是设置了最大的Thenuring Threshold,不是说只有大于Max Tenuring Threshold才会进入到老年代,而是只要超过了计算出来的Tenuring Threshold就会进入老年代,MaxTenuringThreshold规定了Tenuring Threshold的最大值而已。Tenuring Threshold这个值在每一轮GC后都会动态计算,它与TargetSurvivorRatio以及Survivor区的大小有关系,TargetSurivivor默认是50即Survivor的1/2, 会计算出一个Desired Survivor Size,当age从1开始的对象大小累计超过了这个Desired Survivor Size,那么这个age就是Tenuring Threshold的值

5. 一旦对象进入了老年代,那么只有触发CMS(只针对CMS而言)或者Full GC的时候才能被清除

6. Heap什么时候会发生OOM?

  • 当花在GC的时间超过了GCTimeLimit,这个值默认是98%
  • 当GC后的容量小于GCHeapFreeLimit,这个值默认是2%

7. 什么是剩余空间不够?

剩余空间不够不是说整体的空间不够分配某个对象,而是说连续的空间不够分配给某个对象。所以一旦内存碎片大多就可能发生剩余空间不够的问题,所以CMS这种收集器,需要在标记-清除几次之后进行压缩,进行优化。CMSFullGCsBeforeCompaction可以设置进行几次清除之后进行压缩

8. Full GC的次数说的是stop the world的次数,所以一次CMS至少会让Full GC的次数+2,因为CMS Initial mark和remark都会stop the world,记做2次。而CMS可能失败再引发一次Full GC

9. JMI默认会一个小时调用一次System.gc()清理缓存,所以可以DisableExplicitGC,也可以设置sun.rmi.dgc.client.gcInterval和sun.rmi.dgc.server.gcInterval参数来规定JMI清理的时间

10. 对于性能调优来说,应该理解对于给定的硬件,给定的算法(垃圾收集器),单个/多个线程单位时间内能够回收的空间是接近一个常量的。如果想要缩短GC的时候,就要考虑是否要相应调小空间

11. CMS收集器会了减少stop the world的时间,让GC线程和业务线程并发,这样也就相对拉长了CMS收集器单次GC的时间

12. 尽可能地让对象停留在新生代,因为新生代采用了复制算法,相对收回得更快,而且Minor GC的次数肯定比Full GC多,那么对象在新生代被清除的更能性会更高。而对象一旦进入到老年代,那么只有Full GC时才会回收,对象在整个系统停留的时间就会很长,很可能创建的它的线程早就死了,而它还活着

13. 为了尽可能让对象停留在新生代,就要注意设置Survivor区域的大小,因为它直接和对象是否进入老年代相关。之前就遇到过这种情况,明明新生代还有很大的空间,但是每次Minor GC后总是有对象进入到了老年代。后来发现由于Survivor太小,导致Tenuring Threshold为1,意思是年龄为1的对象大小超过了Survivor / 2(可通过TargetSurvivorRatio来调节,默认是50,即1/2),年龄只要超过1的对象这时候就要直接进入老年代了。而进入老年代,对象就只有在Full GC的时候才会被清除。而如果调大了Survivor空间,让对象对象尽量接近Max Tenuring Threshold时才进入到老年代,这时候会大大减少老年代的对象大小,并且让对象在新生代停留时间变长,提高了它们被快速清理出系统的概率。

聊聊JVM(二)说说GC的一些常见概念的更多相关文章

  1. (二)javaweb开发的常见概念总结(来自那些年的笔记)

    目录 WEB开发相关知识 WEB服务器 Tomcat服务器 WEB应用程序 配置WEB应用 配置缺省的WEB应用 Web设置首页 web.xml文件 配置虚拟主机 配置https连接器 为我们的网站, ...

  2. JVM:从实际案例聊聊Java应用的GC优化

    原文转载自美团从实际案例聊聊Java应用的GC优化,感谢原作者的贡献 当Java程序性能达不到既定目标,且其他优化手段都已经穷尽时,通常需要调整垃圾回收器来进一步提高性能,称为GC优化.但GC算法复杂 ...

  3. JVM组成、GC回收机制、算法、JVM常见启动参数、JAVA出现OOM,如何解决、tomcat优化方法

    JVM组成.GC回收机制.算法.JVM常见启动参数.JAVA出现OOM,如何解决.tomcat优化方法

  4. JVM中的GC算法,JVM参数,垃圾收集器分类

    一.在JVM中什么是垃圾?如何判断一个对象是否可被回收?哪些对象可以作为GC Roots的根 垃圾就是在内存中已经不再被使用到的空间就是垃圾. 1.引用计数法: 内部使用一个计数器,当有对象被引用+1 ...

  5. JVM内存管理&GC

    一.JVM内存划分 |--------------------|-------------PC寄存器-------| |----方法区 ---------|--------------java 虚拟机 ...

  6. 聊聊jvm的CompressedClassSpace

    序本文主要研究一下jvm的CompressedClassSpace CompressedClassSpacejava8移除了permanent generation,然后class metadata存 ...

  7. JVM 垃圾回收GC Roots Tracing

    1.跟搜索算法: JVM中对内存进行回收时,需要判断对象是否仍在使用中,可以通过GC Roots Tracing辨别. 定义: 通过一系列名为”GCRoots”的对象作为起始点,从这个节点向下搜索,搜 ...

  8. 聊聊JVM的年轻代(转)

    聊聊JVM的年轻代 本文转自http://ifeve.com/jvm-yong-generation/ 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代 ...

  9. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

随机推荐

  1. mongodb内嵌文档的javaapi,增删改查

    数据结构: {"_id" : "000000001",  //Mongodb默认主键 "UID" : "000000001&quo ...

  2. Oracle获取异常的具体出处dbms_utility.format_error_backtrace

    DBMS_UTILITY.FORMAT_ERROR_BACKTRACE :返回当前异常相应的描述,通过它就能知道异常的最初生成处.   系统为最近一次生成的异常设置了一个栈,并跟踪它的传递过程,而这个 ...

  3. flume接收http请求,并将数据写到kafka

    flume接收http请求,并将数据写到kafka,spark消费kafka的数据.是数据采集的经典框架. 直接上flume的配置: source : http channel : file sink ...

  4. JPA的初级CRUD-01

    一.JPA 1.1 什么是JPA JPA:(Java Persistence API) ORM的规范 JPA是规范,Hibernate是它的实现(不唯一,但最好) 最底层的操作还是JDBC(引入驱动包 ...

  5. Educational Codeforces Round 58 (Rated for Div. 2) F dp + 优化(新坑) + 离线处理

    https://codeforces.com/contest/1101/problem/F 题意 有n个城市,m辆卡车,每辆卡车有起点\(s_i\),终点\(f_i\),每公里油耗\(c_i\),可加 ...

  6. qt字符数组转ASCII(十六进制)

    接收网络传输数据 QByteArray  array;//显示字符串 QString str = QString::fromLocal8Bit(array); m_receiveTxt.append( ...

  7. Java性能优化的50个细节(珍藏版)

    原文地址:https://www.toutiao.com/i6595499804082569742/ 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重 ...

  8. MyBatis-Plus 3.0.3 Sql注入器添加,即全局配置Sql注入器,sqlInjector改写

    官网上写着 但是,这个其实是2.0系列的写法,由于引用了最新的3.0.3这个功能基本不好使. 3.0.3版本的写法 也就是中间加了一层,原来是AutoSqlInjector,现在改为AbstractS ...

  9. You just run!

    第一篇博客,无关技术,有关身体. 写一篇跑步干货 装备篇 用过的鞋: 光脚,拖鞋,人字拖,回力板鞋,皮鞋,特步,鸿星尔克,李宁超轻13,ASICS  gt2000,阿迪低端. 1,非常推荐攒钱买一双a ...

  10. grep 笔记

    -a :将 binary 文件以 text 文件的方式搜寻数据-c :计算找到 '搜寻字符串' 的次数-i :忽略大小写的不同,所以大小写视为相同-n :顺便输出行号-v :反向选择,亦即显示出没有 ...