【转帖】一道面试题:JVM老年代空间担保机制
面试问题
昨天面试的时候,面试官问的问题:
- 什么是老年代空间担保机制?担保的过程是什么?
- 老年代空间担保机制是谁给谁担保?
- 为什么要有老年代空间担保机制?或者说空间担保机制的目的是什么?
- 如果没有老年代空间担保机制会有什么不好?
下面我们就带着这些问题去了解一下JVM老年代空间担保机制吧。
老年代空间担保机制

如图,在每次MinorGC之前,老年代可用空间会和新生代所有对象的总大小进行对比,如果老年代可用空间大于新生代所有对象的总大小,就可以直接进行MinorGC,因为即使MinorGC后所有对象都活着,S区放不下,也可以放到老年代中。如果老年代的可用空间小于新生代所有对象的总大小,就会进行下一个判断,判断老年代的可用空间和新生代每次MinorGC后进入老年代对象的平均大小,如果发现老年代的可用内存大于每次MinorGC后进入老年代对象的平均大小(举个例子:之前每次Minor GC后,平均都有10MB左右的对象会进入老年代,那么此时老年代可用内存大于10MB。这就说明很可能这次Minor GC过后也是差不多10MB左右的对象会进入老年代,此时老年代空间是够的),那么可以尝试进行MinorGC,但是有可能出现MinorGC后所有对象都存活,全部进去老年代,导致老年代可用空间不足,(例:老年代剩余100M,新生代中对象总大小为200M,但是每次MinorGC后平均进入老年代的对象大小为80M,但是此次MinorGC后所有对象全部存活,导致老年代可用空间不足)此时就会触发FullGC。反之,如果老年代的可用空间小于每次MinorGC后进入老年代对象的平均大小,则会触发FullGC。如果FullGC之后,老年代也没有足够的可用空间存放新生代的对象,则会出现OOM内存溢出。
了解了这个担保流程之后,我们再来看我们的面试题:
- 什么是老年代空间担保机制?担保的过程是什么?
上面文字解释的就是。 - 老年代空间担保机制是谁给谁担保?
我理解的是老年代给新生代的S区做担保。 - 为什么要有老年代空间担保机制?或者说空间担保机制的目的是什么?
目的:避免频繁的进行FullGC。 - 如果没有老年代空间担保机制会有什么不好?
如果没有这个担保机制,就会直接执行Full GC,这样对性能的影响频次会增加。
哪些对象会进行老年代
- 动态对象年龄判断:当前放对象的Survivor区域里,一批对象的总大小大于了这块Survivor区域的内存大小的50%,那么此时大于等于这批对象年龄的对象,就可以直接进入老年代了。
- 大对象直接进入老年代。
- 15次Minor GC后还存活的对象。
- Minor GC后的对象太多无法放入Survivor区。
Full GC的触发时机
- 老年代空间不足。比如大对象或者年龄超过15的对象进入老年代。
- 空间分配担保失败。这个就是咱们今天说的这种情况。老年代可用内存小于新生代全部对象的大小,如果没开启空间担保参数,会直接触发Full GC,所以一般空间担保参数都会打开。
- Concurrent Mode Failure 执行CMS GC的过程中同时有对象要进入老年代,而此时老年代空间不足(可能是GC过程中浮动垃圾过多导致暂时性的空间不足)便会报Concurrent Mode Failure错误并触发Full GC。这种情况下会使用Serial Old收集器,也就是发生了退化,CMS退化为serial gc,Serial Old收集器是单线程的,对GC的影响很大。concurrent mode failure产生的原因是老年代剩余的空间不够,导致了和gc线程并发执行的用户线程创建的大对象(由PretenureSizeThreshold控制新生代直接晋升老年代的对象size阀值)不能进入到老年代,只要stop the world来暂停用户线程,执行GC清理,单线程对全堆以及 metaspace 进行回收,STW 的时间会特别长,对业务系统的可用性影响比较大。可以通过设置CMSInitiatingOccupancyFraction预留合适的CMS执行时剩余的空间。
- 老年代可用内存小于历次新生代GC后进入老年代的平均对象大小,此时会提前Full GC;但是"-XX:HandlePromotionFailure"参数,在JDK 1.6以后就被废弃了,所以现在一般都不会在生产环境里设置这个参数了。在JDK 1.6以后,只要判断"老年代可用空间"大于"新生代对象总和"或者"老年代可用空间"大于"历次Minor GC升入老年代对象的平均大小",两个条件满足一个,就可以直接进行Minor GC,不需要提前触发Full GC了。
- 新生代Minor GC后的存活对象大于Survivor,那么就会进入老年代,此时老年代内存不足,触发Full GC。这里的不足就是判断条件后还是不足或者经过判断后进行YGC后放入老年代此时的空间不足,然后进行Full GC,就会出现频繁Full GC。达到一定情况后,就会OOM了。
- 如果用的是CMS收集器,老年代可用内存大于历次新生代GC后进入老年代的对象平均大小,但是老年代已经使用的内存空间超过了("-XX:CMSInitiatingOccupancyFaction=92%"JDK6默认值 )这个参数指定的比例,也会自动触发Full GC。
- 未指定老年代和新生代大小,堆伸缩时会触发Full GC。
- 调用System.gc(),只是建议虚拟机执行Full GC,但虚拟机不一定真正去执行。
【转帖】一道面试题:JVM老年代空间担保机制的更多相关文章
- JVM老年代和新生代的比例
在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old ).新生代 ( Young ) 又被划分为三个区域:Eden.From Survivor.To Surviv ...
- 看图说说JVM老年代垃圾收集器
注:G1垃圾收集器是目前最前沿的GC收集器,未来将取代CMS垃圾收集器,可以作为整个Heap的收集器使用,不限于老年代!!!
- “每日一道面试题”.Net中GC的运行机制
GC 也就是垃圾回收,经常遇到的面试题,关于GC 感觉可以写一本书,我们要做的也就是简单理解,如果有意愿,可以深入研究 所谓的垃圾回收,也就是清理回收托管堆上不再被使用的对象内存,并且移动仍在被使用的 ...
- 一道面试题引发对javascript事件循环机制(Event Loop)的 思考(这里讨论针对浏览器)
- JVM之堆内存(年经代,老年代)
一.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我 ...
- JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代
内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...
- JVM进入老年代情况
1.躲过15次GC之后进入老年代 默认的设置下,当对象的年龄达到15岁的时候,也就是躲过15次Gc的时候,他就会转移到老年代中去 这个具体是多少岁进入老年代,可以通过JVM参数 “-XX:MaxTen ...
- java GC jvm 内存分布 和新生代,老年代,永久代,(详细)
如果大家想深入的了解JVM,可以读读周志明<深入理解Java虚拟机:JVM高级特性与最佳实践> 需要掌握的东西,包括以下内容.判断对象存活还是死亡的算法(引用计数算法.可达性分析算法).常 ...
- java 虚拟机--新生代与老年代GC [转]
原文链接:http://www.360doc.com/content/12/1023/16/9615799_243296263.shtml 1. Java堆中各代分布: 图1:Java堆中各代分布 Y ...
- 【转】Java中的新生代、老年代、永久代和各种GC
JVM中的堆,一般分为三大部分:新生代.老年代.永久代: 1 新生代 主要是用来存放新生的对象.一般占据堆的1/3空间.由于频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收. 新生代又分为 ...
随机推荐
- 未加载mscorlib.pdb
前言: 早上上班按照正常流程打开Visual Studio,调试本地项目,然后奇怪的是一直提示未加载mscorlib.pdb,导致项目无法正常运行,经过一番折腾最后解决了这个突如其来的bug! 问题重 ...
- Java 插入Excel页眉、页脚
前言 在Excel文档中,我们常用页眉页脚来显示文档的附加信息,例如日期.公司名称.Logo或作者信息等.本文将通过Java程序来介绍如何给Excel文档添加页眉页脚.代码示例主要从以下几方面来演示添 ...
- Navicat 携手华为云GaussDB,联合打造便捷高效的数据库开发和建模工具方案
本文分享自华为云社区<Navicat 携手华为云GaussDB,联合打造便捷高效的数据库开发和建模工具方案>,作者: GaussDB 数据库 . 近日, Navicat Premium顺利 ...
- MySQL事务处理特性的实现原理
摘要:事务这个词来自于英语中的transactional这个词的翻译,这个词的含义更多的是指 "交易".在数据库系统或者软件系统中我们通常 称 transactional 为事务 ...
- nginx网站限速限流配置——网站被频繁攻击,nginx上的设置limit_req和limit_conn
利用ngx_http_limit_req_module模块,可根据键值(如ip)限制每分钟的速率: limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 "l ...
- 火山引擎 DataTester:如何做 A/B 实验的假设检验
A/B 实验的核心统计学理论是(双样本)假设检验,是用来判断样本与样本.样本与总体的差异是由 抽样误差 引起还是 本质差别 造成的一种统计推断方法. 假设检验,顾名思义,是一种对自己做出的假设进行数据 ...
- Java 线程间通信 —— 管道输入 / 输出流
本文部分摘自<Java 并发编程的艺术> 管道输入 / 输出流 管道输入 / 输出流和普通的文件输入 / 输出流或者网络输入 / 输出流不同之处在于,它主要用于线程之间的数据传输,而传输媒 ...
- Jetpack初步了解
1.为何要引入Jetpack呢? 通常来说,一个Android应用程序至少需要一个Activity,当我们开发小型Android程序时,可能会将大部分代码写在Activity/Fragment中,例如 ...
- WCF 动态调用 动态代理
关键词:WCF动态调用.动态调用WCF.WCF使用动态代理精简代码架构.使用反射执行WCF接口 代码地址: https://gitee.com/s0611163/DynamicWCF https:// ...
- GitHub CEO发文:严格限制俄罗斯获取侵略性军事能力所需要的技术
前几天,在微信群里就有小伙伴发了一些关于GitHub将限制俄罗斯开发人员使用开源软件的消息,引起程序员圈子的热烈讨论. 就在不久前,GitHub CEO在GitHub官方博客发文阐述了对乌克兰战争的回 ...