JVM年轻代和老年代垃圾回收
复制算法
- 概述
复制算法将内存划分为两个区间,在任意时间点,所有动态分配的对象都只能分配在其中一个区间(称为活动区间),而另外一个区间(称为空闲区间)则是空闲的。
当有效内存空间耗尽时,JVM将暂停程序运行,开启复制算法GC线程。接下来GC线程会将活动区间内的存活对象,全部复制到空闲区间,且严格按照内存地址依次排列,与此同时,GC线程将更新存活对象的内存引用地址指向新的内存地址。
- 复制算法优点
- 保证空间的连续性,不会出现"碎片"问题。
- 没有标记和清除过程,实现简单,运行高效
- 复制算法的优化
内存划为1个Eden区,2个Survivor区,其中Eden区占80%内存空间,每一块Survivor区各占10%内存空间,比如说Eden区有800MB内存,每一块Survivor区就100MB内存。
Survivor区,一块叫From,一块叫To,对象存在Eden和From块。当进行GC时,Eden存活的对象全移到To块,而From中,存活的对象按年龄值确定去向,当达到一定值的对象会移到年老代中,没有达到值的复制到To区,经过GC后,Eden和From被清空。之后,From和To交换角色,新的From即为原来的To块,新的To块即为原来的From块,且新的To块中对象年龄加1。
注:年龄阈值可通过-XX:MaxTenuringThreshold可设置
MinorGC过程
- 触发时机:
Eden区满时会触发,但是Survivor区域满了不会引发GC
- 解释
代码在运行的过程中,就会不断的创建各种各样的对象,这些对象都会优先放到新生代的Eden区和Survivor1区。
假如新生代的Eden区和Survivor1区都快满了,此时就会触发Minor GC,把存活对象转移到Survivor2区去。此时就会把Eden区中的存活对象都一次性转移到一块空着的Survivor区。接着Eden区就会被清空。
然后再次分配新对象到Eden区里,Eden区和一块Survivor区里是有对象的,其中Survivor区里放的是上一次Minor GC后存活的对象。如果下次再次Eden区满,那么再次触发Minor GC,就会把Eden区和放着上一次Minor GC后存活对象的Survivor区内的存活对象,转移到另外一块Survivor区去。
对象进入老年代的情况
根据对象年龄
对象每次在新生代里躲过一次MinorGC然后被转移到一块Survivor区域中,那么它的年龄就会增长一岁,默认的设置下,当对象的年龄达到15岁的时候,也就是躲过15次GC的时候,他就会转移到老年代里去。这个具体是多少岁进入老年代,可以通过JVM参数“-XX:MaxTenuringThreshold”来设置,默认是15岁。
动态对象年龄判断
还有另外一个规则可以让对象进入老年代,不用等待15次GC过后才可以。
当前Survivor区域里,一批对象的总大小超过了这块Survivor区域的内存大小的50%,那么此时大于等于这批对象年龄的对象,就可以直接进入老年代了。
假设这个图里的Survivor2区有三个对象,这些对象的年龄一样,都是3岁然后俩对象加起来对象超过了50MB,超过了Survivor2区的100MB内存大小的一半了,这个时候,Survivor2区里的大于等于3岁的对象,就要全部进入老年代里去。这就是所谓的动态年龄判断的规则,这条规则也会让一些新生代的对象进入老年代。
另外这里要理清楚一个概念,就是实际这个规则运行的时候是如下的逻辑:年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区域的50%,此时就会把年龄n以上的对象都放入老年代。
大对象直接进入老年代
有一个JVM参数,就是“-XX:PretenureSizeThreshold”,可以把他的值设置为字节数,比如“1048576”字节,就是1MB。意思就是,如果你要创建一个大于这个大小的对象,比如一个超大的数组,或者是别的啥东西,此时就直接把这个大对象放到老年代里去。不会经过新生代。之所以这么做,就是要避免新生代里出现那种大对象,然后屡次躲过GC,然后在两个Survivor区域里来回复制多次之后才能进入老年代,
Minor GC后的对象太多
在Minor GC之后发现剩余的存活对象太多了,没办法放入另外一块Survivor区,此时就必须得把这些对象直接转移到老年代去
老年代空间分配担保规则
- 问题引出
如果新生代里有大量对象存活下来,确实是自己的Survivor区放不下了,必须转移到老年代去,那么如果老年代里空间也不够放这些对象怎么处理?
- 解决
首先,在执行任何一次Minor GC之前,JVM会先检查一下老年代可用的可用内存空间,是否大于新生代所有对象的总大小。防止最极端的情况下,可能新生代Minor GC过后,所有对象都存活下来了新生代所有对象全部要进入老年代。
如果说发现老年代的内存大小是大于新生代所有对象的,此时就可以对新生代发起一次Minor GC了,因为即使Minor GC之后所有对象都存活,Survivor区放不下了,也可以转移到老年代去。
假如执行Minor GC之前,发现老年代的可用内存已经小于了新生代的全部对象大小了那么这个时候有可能在Minor GC之后新生代的对象全部存活下来,然后全部需要转移到老年代去,但是老年代空间又不够。所以假如Minor GC之前,就会看一个“-XX:-HandlePromotionFailure”的参数是否设置了 ,如果有这个参数,那么就会继续尝试进行下一步判断。
- 查看老年代的内存大小,是否大于之前每一次Minor GC后进入老年代的对象的平均大小。
例如:之前每次Minor GC后,平均都有10MB左右的对象会进入老年代,那么此时老年代可用内存大于10MB。这就说明,很可能这次Minor GC过后也是差不多10MB左右的对象会进入老年代,此时老年代空间是够的,就可以进行回收。
- 如果上面那个步骤判断失败了,或者是“-XX:-HandlePromotionFailure”参数没设置,此时就会直接触发一次“Full GC”,就是对老年代进行垃圾回收,尽量腾出来一些内存空间,然后再执行Minor GC。
总结
在发生Minor GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间。
- 如果大于,则此次Minor GC是安全的
- 如果小于,则虚拟机会查看-XX:-HandlePromotionFailure设置值对否允许担保失败.
- 如果HandlePromotionFailure=true,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的对象的平均大小
- 如果大于,则尝试进行一次Minor GC,但这次Minor GC依然是有风险的;如果回收后存活对象大于Survivor区域的大小,也大于了老年代可用内存的大小,就会发生"Handle Promotion Failure"的情况,这个时候就会触发一次"Full GC"
- 如果小于,则改为进行一次Full GC。
- 如果HandlePromotionFailure=false,则改为进行一次Full GC
- HandlePromotionFailure参数在JDK7之后就失效了,只要老年代的连续空间大于新生代对象的总大小或者大于历次晋升到老年代的对象的平均大小就进行MonitorGC,否则FullGC
老年代垃圾回收算法
标记 - 整理算法
复制收集算法在对象存活率较高时需要进行较多的复制操作,效率将会降低。更关键的是,如果不想浪费50%的内存空间,就需要提供额外的空间进行分配担保。由于老年代中对象存活率较高,而且找不到其他内存进行分配担保,所以老年代一般不能直接选用这种收集算法。
根据老年代的特点,有人对“标记 - 清除”进行改进,提出了“标记 - 整理”算法。“标记 - 整理”算法的标记过程与“标记 - 清除”算法相同,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
触发时机
调用System.gc时,系统建议执行Full GC,但是不必然执行
老年代空间不足
空间分配担保失败
JDK 1.7 及以前的永久代(方法区)空间不足
通过Minor GC后进入老年代的平均大小大于老年代的可用内存
CMS GC处理浮动垃圾时,如果新生代空间不足,则采用空间分配担保机制,如果老年代空间不足,则触发Full GC
Old GC执行的时带上一次Young GC
- OldGC触发条件
发生Young GC之前进行检查,如果“老年代可用的连续内存空间” < “新生代历次Young GC后升入老年代的对象总和的平均大小”,说明本次Young GC后可能升入老年代的对象大小,可能超过了老年代当前可用内存空间此时必须先触发一次Old GC给老年代腾出更多的空间,然后再执行Young GC
执行Young GC之后有一批对象需要放入老年代,此时老年代就是没有足够的内存空间存放这些对象了,此时必须立即触发一次Old GC(老年代剩余空间大于历次年轻代进入老年代的平均大小,但是本次回收后进入老年代的对象远大于历次的平均大小)
老年代内存使用率超过了92%,也要直接触发Old GC,当然这个比例是可以通过参数调整的
简单点说就是,就是老年代空间也不够了,没法放入更多对象了,这个时候务必执行Old GC对老年代进行垃圾回收。
- 解释
如果是条件1引起的Old GC 那么说明老年代空间不足,无法进行Young GC,需要先进行一次Old GC然后再进行Young GC,这样Old GC就发生在 Yonug GC之前
如果是条件2引起的,那么就是Young GC后空间不足,进而引发Old GC
在很多JVM的实现机制里,其实在上述几种条件达到的时候他触发的实际上就是Full GC,这个Full GC会包含Young GC、Old GC和永久代的GC
JVM年轻代和老年代垃圾回收相关推荐
- JVM年轻代,老年代,永久代详解
秉承不重复造轮子的原则,查看印象笔记分享连接↓↓↓↓ 传送门:JVM年轻代,老年代,永久代详解 速读摘要 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.在 ...
- JVM年轻代,老年代,永久代详解
前言 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.本篇文章主要讲解内存区域的年轻代,老年代和永久代,略微提及一些垃圾回收算法,下面是正文. 堆整体 堆主 ...
- Java --- JVM年轻代与老年代
一.年轻代与老年代 1.存储在VM中的Java对象可以被划分为两类:①.一类是生命周期较短的瞬时对象,这类对象的创建和消亡都非常迅速.②.另外一类对象的生命周期却非常长,在某些极端的情况下还能够与VM ...
- Java的垃圾回收机制、年轻代与老年代
目录 1 被判定为垃圾的标准 2 判定对象是否为垃圾的算法 2.1 引用计数法 2.2 可达性分析算法 3 垃圾回收的算法 3.1 标记-清除算法(Mark and Sweep) 3.2 复制算法(C ...
- JVM学习笔记之-堆,年轻代与老年代,对象分配过程,Minor GC、Major GC、Full GC,堆内存大小与OOM,堆空间分代,内存分配策略,对象分配内存,小结堆空间,逃逸分析,常用调优工具
堆的核心概述 概述 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域.Java堆区在JVM 启动的时候即被创建,其空间大小也就确定了.是JVM管理的最大一块内存空间. 堆内存的大小是可 ...
- JVM专题之分代模型:年轻代、老年代、永久代
目录 一 什么是GC 分代 二 GC 为什么需要分代 三 GC 如何分代,每一个代具体是怎么工作的 3.1 年轻代 3.1.1 Eden Space 3.1.2 Survivor 3.2 老年代 3. ...
- jvm中年轻代,老年代
jvm中新生代,老年代 一.年轻代 二.老年代 三.永久代 Java中的Heap(堆)是JVM所管理的最大的一块内存空间,主要用于存放各种类的实例对象. 由于Java堆是垃圾收集器管理的主要区域,因此 ...
- 年轻代,老年代,永久代
首相明确一点,年轻代和老年代属于堆:永久代属于在Hotspot虚拟机下对方法区的实现,并不存在于堆中. 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old).新 ...
- 5、JVM分代模型--新生代 的垃圾回收
为什么要有JVM分代模型? JVM中的对象生命周期不同,有的对象长期存在,而有的对象朝生夕死,对象生命周期的不同直接导致了进行垃圾回收时存活对象比例不同,而存活对象比例不同就导致需要使用不同的垃圾回收 ...
- Major GC 是清理老年代。 Full GC 是清理整个堆空间—包括年轻代和老年代。
Major GC 是清理老年代. Full GC 是清理整个堆空间-包括年轻代和老年代.
最新文章
- 硬铺路、软筑墙:三星移动在中国的新路径
- 零基础学python看什么书-零基础学python推荐几本python学习的书籍
- 能分清直方图和柱状图,你就是图表届的“头号”玩家|图表家族#36
- linux下VMware_Tools虚拟机工具的安装
- string类有可以调换方向的函数吗_String类中常用的操作
- 【安富莱二代示波器教程】第8章 示波器设计—测量功能
- 蚂蚁金服自研数据库OceanBase如何登顶TPC-C
- C语言实现AES加密解密
- Microsoft .NET Pet Shop 4.0 学习之旅(二) - 项目的引用关系1
- Android源码解析:UI绘制流程之测量.md
- 2 CO配置-企业结构-定义-维护成本控制范围(Controlling Area)
- ONNX系列六 --- 在Java中使用可移植的ONNX AI模型
- pdf覆盖图片 Java_Java 添加、替换、删除PDF中的图片的示例代码
- TranslateMessage 和 DispatchMessage
- 算法设计与分析知识点整理
- 软件构造之java类图
- mysql 词频分析工具_hive进行词频统计
- Ubuntu20.04上安装Gnuradio3.8并且实现Pluto的配置
- stm32定时器的ETR、CH1N、CH2N、CH3N
- 知网导出之Excel
热门文章
- 联发科mt8516价格_揭秘联发科MT8516单颗芯片破千万背后的故事
- 传统蓝牙BR/EDR的搜索Inquiry
- 不同速度流体的剪切形成不同尺度的漩涡,看起来很像分形。
- 利用weevely生成php后门木马
- java applica_下列关于 Java Application 程序在结构上特点的描述中,错误的是 ()_实用英语2答案_学小易找答案...
- thinkphp下载MP4视频
- maven 实战 (许晓斌)
- 安装protobuf可能遇到的问题
- 局域网oracle 速度慢,[转帖]局域网中其他用户感觉上网速度慢、网速卡
- 两种常见的台式计算机,win7电脑定时关机的两种最常用方法【图文】