[转帖]JVM中年轻代里的对象什么情况下进入老年代?以及老年代垃圾回收算法-标记整理算法
1.躲过15次GC之后进入老年代
系统刚启动时,创建的各种各样的对象,都是分配在年轻代里。
随着慢慢系统跑着跑着,年轻代满了,就会出发Minor GC ,可能1%的少量存活对像转移到空着的Survivor区中
然后系统继续运行,继续在Eden区里分配对象........
.....
类似静态变量等引用的对象,可能存活时间会久一些,无论年轻代中怎么垃圾回收,类似这种对象都不会被回收掉。
而此对象每次在年轻代里躲过一次Minor GC被转移到一块Survivor区域中,他的年龄就会增加一岁
默认的设置下,当对象的年龄达到15岁时,也就是躲过15次GC的时候,他就会转移到老年代里去。
具体是多少岁进入老年代,可以通过JVM参数“-XX:MaxTenuringThreshold”来设置,默认是15岁
2.动态对象年龄判断
这里跟这个对象年龄有另外一个规则可以让对象进入老年代,不用等到15次GC过后才可以。
他的大致规则就是,假如说当前放对象的Survivor区域里,一批对象的总大小大于了这块Survivor区域的内存大小的50%,那么此时大于等于这批对象年龄的对象,就可以直接进入老年代了。

假设这个图中的Survivor2区有两个对象,这俩对象的年龄一样,都是2岁
然后俩对象加起来内存超过了50MB,这个时候,Survivor2区里大于等于2岁的对象,都要进入老年代里去。
这就是动态年龄判断的规则,这条规则也会让一些年轻代的对象进入老年代
另外实际这个规则运行的时候是如下的逻辑:年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区的50%,此时就会把年龄n以上的对象都放入老年代。
3.大对象直接进入老年代
有一个JVM参数,就是“-XX:PretenureSizeThreshold”,可以把它的值设置为字节数,比如“1048576”字节,就是1MB
意思就是如果你要创建一个大于这个大小的对象,比如一个超大的数组,或者是别的啥东西,此时就直接把这个大对象放到老年代里去,压根不会经过年轻代。
之所以这么做,是因为要避免年轻代里出现那种大对象,然后屡次躲过GC,还得把他在两个Survivor区域里来回复制多次之后才能进入老年代。
所以说这也是一个对象进入老年代的规则
4.Minor GC后的对象太多,无法放入Survivor区
如图所示:

这个时候就必须得把这些对象直接转移到老年代去!
5.老年代空间分配担保规则
如果年轻代里大量对象存活,确实自己的Survivor区放不下了,必须转移到老年代去
但是如果老年代里空间也不够放这些对象,改怎么办呢?
首先,在执行任何一次Minor GC之前,JVM都会先检查一些老年代可用的内存空间,是否大于年轻代所有对象的总大小
问什么呢?因为最极端的情况下,可能年轻代Minor GC之后,所有对象都存活下来了,那岂不是年轻代所有对象全部进入老年代

如果说发现老年代内存大小是大于年轻代所有对象的,此时就可以放心大胆地对年轻代发起一次Minor GC了。
但是假如执行Minor GC之前,发现老年代的可用内存已经小于了年轻代的全部对象大小了
恰好这个时候Minor GC之后年轻代的对象全部存活下来,全部需要转移到老年代中去,但是老年代内存空间又不够?
所以假如Minor GC之前,发现老年代的可用内存已经小于了年轻代的全部对象大小,就会看一个“-XX:-HandlePromotionFailure”的参数是否设置了
如果有这个参数,那么就会看看老年代的内存大小,是否大于之前每一次Minor GC后进去老年代对象的平均大小

但是如果上面步骤判断失败了,或者是“-XX:-HandlePromotionFailure”参数没设置,此时就会直接触发一次“Full GC”,
就是对老年代进行垃圾回收,尽量腾出来一些内存空间,然后再执行Minor GC。
如果上面两个步骤判断成功,那么就可以尝试Minor GC,此时进行Minor GC有几种可能:
①Minor GC过后,剩余的存活对象的大小,小于Survivor区的大小,那么此时存活对象进入Survivor区即可
②Minor GC过后,剩余的存活对象的大小,大于Survivor区的大小,但是小于老年代可用内存大小,就直接进入老年代即可
③Minor GC过后,剩余的存活对象的大小,大于Survivor区的大小,同时大于老年代可用内存大小,此时就会发生“Handle Promotion Failure”的情况,这个时候就会出发一次“Full GC”。
Full GC就是对老年代进行垃圾回收,同时也一般会对年轻代进行垃圾回收。
如果Full GC之后,老年代还是没有足够空间存放Minor GC过后的剩余存活对虾,此时就会导致所谓的“OOM”内存溢出了。
6.老年代垃圾回收算法
老年代触发垃圾回收的机制,一般就是两个;
①在Minor GC之前,一通检查发现很可能Minor GC之后要进入老年代的对象太多了,老年代放不下,此时需要提前触发Full GC再然后再带着进行Minor GC;
②要不然是在Minor GC之后,发现剩余对象太多放入老年代都放不下了。
老年代采取的垃圾回收算法是标记整理算法。
看下面图,首先标记出来老年代当前存活的对象,这些对象可能是东一个西一个的

接着会让这些存活对象在内存里进行移动,把存活对象尽量都挪动到一边去,让存活对象紧凑的靠在一起,避免垃圾回收过后出现过多的内存碎片
然后再一次性把垃圾对象都回收掉,如下图

老年代的垃圾回收算法的速度至少比年轻代的垃圾回收算法的速度慢10倍。
如果系统频繁出现老年代的Full GC垃圾回收,会导致系统性能被严重影响,出现频繁卡顿的情况。
所以,所谓的JVM优化,就是尽可能的让对象都在年轻代里分配和回收,尽量别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免年轻代频繁的进行垃圾回收。
[转帖]JVM中年轻代里的对象什么情况下进入老年代?以及老年代垃圾回收算法-标记整理算法的更多相关文章
- JVM内存管理------GC算法精解(复制算法与标记/整理算法)
本次LZ和各位分享GC最后两种算法,复制算法以及标记/整理算法.上一章在讲解标记/清除算法时已经提到过,这两种算法都是在此基础上演化而来的,究竟这两种算法优化了之前标记/清除算法的哪些问题呢? 复制算 ...
- JVM内存管理之GC算法精解(复制算法与标记/整理算法)
本次LZ和各位分享GC最后两种算法,复制算法以及标记/整理算法.上一章在讲解标记/清除算法时已经提到过,这两种算法都是在此基础上演化而来的,究竟这两种算法优化了之前标记/清除算法的哪些问题呢? 复制算 ...
- 聊聊JVM的年轻代
1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的 唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候 ...
- 聊聊JVM的年轻代(转)
聊聊JVM的年轻代 本文转自http://ifeve.com/jvm-yong-generation/ 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代 ...
- JVM之GC算法、垃圾收集算法——标记-清除算法、复制算法、标记-整理算法、分代收集算法
标记-清除算法 此垃圾收集算法分为“标记”和“清除”两个阶段: 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记对象,它的标记过程前面已经说过——如何判断对象是否存活/死去 死去的对象就会 ...
- JVM虚拟机(四):JVM 垃圾回收机制概念及其算法
垃圾回收概念和其算法 谈到垃圾回收(Garbage Collection)GC,需要先澄清什么是垃圾,类比日常生活中的垃圾,我们会把他们丢入垃圾箱,然后倒掉.GC中的垃圾,特指存于内存中.不会再被使用 ...
- jvm垃圾回收机制和常见算法
这是朋友给的面试题里边的,具体地址已经找不到,只能对原作者说声抱歉了: 理论上来讲sun公司只定义了垃圾回收机制规则,而步局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同. GC(Gar ...
- JVM垃圾回收机制和常用算法
由于疫情的原因,所以目前一直在家远程办公,所以很多时间在刷面试题,发现2019大厂的面试虽然种类很多,但是总结了一下发现主要是这几点:算法和数据结构. JVM.集合.多线程.数据库这几点在面试的时候比 ...
- 在jsp中选中checkbox后 将该记录的多个数据获取,然后传到Action类中进行后台处理 双主键情况下 *.hbm.xml中的写法
在jsp中选中checkbox后 将该记录的多个数据获取,然后传到Action类中进行后台处理 双主键情况下 *.hbm.xml中的写法 ==========方法1: --------1. 选相应 ...
- JVM 垃圾回收机制和常见算法
垃圾回收机制:释放那些不再持有引用的对象的内存. 如何判断对象是否需要回收? 引用计数:对象,内存,磁盘空间等被引用次数保存起来,次数为0时将其进行释放. 对象引用遍历:对象应用遍历从一组对象开始,沿 ...
随机推荐
- linux云服务器病毒处理
阿里云服务器被挖矿病毒入侵,CPU跑满,需要先停止相关进程.为了根除病毒,还需要 解决系统的后门问题(这部分听从阿里云工程师的建议备份系统盘快照后重置系统,再通过快照恢复数据) 然而重置系统后依然存在 ...
- 38. 干货系列从零用Rust编写负载均衡及代理,负载均衡中ip通行与禁止
wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代 ...
- 终于肝完了!全网最全、最详细、最全面的 Hadoop大数据学习教程( 2023最新版 )
大家好,我是民工哥! 前面给大家介绍了:关系型数据库 MySQL . NoSQL 数据库 Redis . MongoDB .搜索引擎 ElasticSearch 等知识体系学习的文章. 在当今这样的就 ...
- JavaFx之TableView表格添加按钮删除行(二十二)
JavaFx之TableView表格添加按钮删除行(二十二) JavaFx之TableView添加按钮 JavaFx之TableView删除行 编写一个xml <?xml version=&qu ...
- k8s卷管理-2
目录 k8s卷管理-2 pv和pvc pv pv的定义 pvc pvc的定义 pv和pvc的绑定关系 手动指定pv与pvc绑定 pod使用pvc pod挂载pvc 访问模式的区别 k8s卷管理-2 之 ...
- UE5:相机震动CameraShake源码分析
本文将会分析UE5中相机震动的调用流程,会简要地分析UCameraModifier_CameraShake.UCameraShakeBase等相关类的调用过程. 阅读本文,你至少需要使用或者了解过Ca ...
- vue点击图片获取图片原像素坐标
<template> <div> <img ref="image" width="1500px" :src="image ...
- Langchain-Chatchat项目:2.1-通过GPT2模型来检索NebulaGraph
在官方例子中给出了通过chain = NebulaGraphQAChain.from_llm(ChatOpenAI(temperature=0), graph=graph, verbose=Tru ...
- Spring Cloud 学习推荐
学习 Spring Boot Spring tutorials | Java Web Development, Spring Cloud Programming tutorials Spring Bo ...
- 从部署和运维说说DLI(1)
DLI是支持多模引擎的Serverless大数据计算服务,其很好的实现了Serverless的特性: 1. 弱化了存储和计算之间的联系: 2. 代码的执行不再需要手动分配资源: 3. 按使用量计费 ...