内存分配与回收策略及MinorGC、MajorGC、FullGC介绍

2024-08-23 22:48

本文主要是介绍内存分配与回收策略及MinorGC、MajorGC、FullGC介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本节将会介绍一下:对象的内存分配与回收策略;对象何时进入新生代、老年代;MinorGC、MajorGC、FullGC的定义区别和触发条件;还有通过图示展示了GC的过程。

目录

对象内存分配与回收策略

对象何时进入新生代、老年代

三种GC介绍

MinorGC

Major GC/Full GC:

图示GC过程


对象内存分配与回收策略

对象的内存分配,往大方向讲,就是在堆上分配〔但也可能经过JIT编译后被拆散为标量类型并间接地栈上分配),对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配。少数情况下也可能会直接分配在老年代中。

对象优先分配在Eden区,当Eden区可用空间不够时会进行MinorGC

大对象直接进入老年代:大对象即需要大量连续内存空间的对象(例如很长的字符串及数组)。虚拟机提供了一个-XX:PretenureSizeThreshoId参数,令大于这个设置值的对象直接在老年代分配,这样做的目的是避免在Eden区及两个区之间发生大量的内存复制。注意PretenureSizeThreshoId参数只对Serial和ParNew两款收集器有效

长期存活的对象将进入老年代:虚拟机给每个对象定义了一个对象年龄(Age)计数器(存在于对象头中)。如果对象在Eden出生并经过第一次MinorGC后仍然存活,并且能被Survivor容纳的话,将被移动到Survwor空间中,并且对象年龄设为1。对象在Survivor区中每“熬过”一次MinorGC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁),就将会被晋升到老年代中。对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshoId设置。

动态年龄判断:为了能更好地适应不同程序的内存状况,虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进人老年代,无须等到MaxTenuringThreshoId中要求的年龄。

 空间分配担保:在发生Minor GC之前,虚拟机会先检查Survivor空间是否够用,如果够用则直接进行Minor GC。否则进行检查老年代最大连续可用空间是否大于新生代的总和,假如大于,那么这个时候发生Minor GC是安全的。假如不大于,那么需要判断HandlePromotionFailure设置是否允许担保失败。假如允许,则继续判定老年代最大可用的连续空间是否大于平均晋升到老年代对象的平均值,如果大于,这个时候可以发生Minor GC ,如果小于或者设置HandlePromotionFailure不允许担保失败,则需要做一次Full GC。通常会把HandlePromotionFailure开关打开,以减少Full GC。

对象何时进入新生代、老年代

新分配的对象一般是直接进入新生代的。但是如果出现以下的情况,会让对象进入老年代。

  • 1.新分配的对象占用空间大于-XX:PretenureSizeThreshold时直接分配到老年代
  • 2.MinorGC的时候,Survivor中的内存不足了,允许分配担保时会进入老年代。
  • 3.MinorGC的时候,对象的年龄大于-XX:MaxTenuringThreshold(默认为15)时,进入老年代。对象年龄存在于对象头中,占4bit。
  • 4.当进行MinorGC的时候,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进人老年代。

三种GC介绍

MinorGC

从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,也叫Young GC。因为Java对象大多具备朝生夕死的特征,所以MinorGC非常频繁,一般回收速度也比较快。一般采用复制算法。

Minor GC触发条件

  • Eden区域满了
  • 新生对象需要分配到新生代的Eden,当Eden区的内存不够时需要进行MinorGC

Major GC/Full GC:

MajorGC:是清理老年代,Major GC发生过程常常伴随一次Minor

FullGC:Full GC可以看做是Major GC+Minor GC共同进行的一整个过程,是清理整个堆空间(包括年轻代和老年代,这里不包含永久代,因为永久代在JDK7之前包含方法区,是一块与堆分离的区域;JDK7将静态变量从永久代移到堆中;JDK8则完全取消永久代,方法区存在元空间MetaSpace中,虽然与堆共享一块内存,逻辑上可以认为在堆中,但仍然与堆不相连)。Full GC的速度一般会比 Minor GC慢10倍以上。一般用的是标记整理和标记清除算法

Full GC触发条件

  • 上面Minor GC时介绍中Survivor空间不足时,判断是否允许担保失败,如果不允许则进行Full GC。如果允许,并且每次晋升到老年代的对象平均大小>老年代最大可用连续内存空间,也会进行Full GC。

  • MinorGC后存活的对象超过了老年代剩余空间
  • 方法区内存不足时
  • System.gc(),可用通过-XX:+ DisableExplicitGC来禁止调用System.gc
  • CMS GC异常,CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,会触发Full GC

图示GC过程

1:初始阶段,对象分配在Eden区(大对象直接进入老年代,通过-XX:PretenureSizeThreshold配置),此时S0和S1是空的(圆圈中的数字代表对象的年龄)

2:当Eden区满了之后,进行MinorGC,经过扫描与标记,不再存活的对象被清除,存活的对象进入Survivor中的S0并且对象年龄+1,此时Eden被清空,S1是空的

 3:然后随着对象增多又一次MinorGC后,Eden区和S0区存活的对象进入S1区并且对象年龄+1,Eden和S0区被清空

 

 4:又一次MinorGC后,和上面步骤类似,Eden区和S1区存活的对象进入S0区并且对象年龄+1,Eden和S1区被清空

 5:对象每熬过一次MinorGC其年龄就会加1,达到年龄阈值(可通过参数-XX:MaxTenuringThreshold配置)的年轻代对象会晋升到老年代,随着进入老年代的对象越来越多,当老年代内存不够用时会发送MajorGC。

 

 

这篇关于内存分配与回收策略及MinorGC、MajorGC、FullGC介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1100717

相关文章

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

java内存泄漏排查过程及解决

《java内存泄漏排查过程及解决》公司某服务内存持续增长,疑似内存泄漏,未触发OOM,排查方法包括检查JVM配置、分析GC执行状态、导出堆内存快照并用IDEAProfiler工具定位大对象及代码... 目录内存泄漏内存问题排查1.查看JVM内存配置2.分析gc是否正常执行3.导出 dump 各种工具分析4.

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

zookeeper端口说明及介绍

《zookeeper端口说明及介绍》:本文主要介绍zookeeper端口说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、zookeeper有三个端口(可以修改)aVNMqvZ二、3个端口的作用三、部署时注意总China编程结一、zookeeper有三个端口(可以

Ubuntu如何分配​​未使用的空间

《Ubuntu如何分配​​未使用的空间》Ubuntu磁盘空间不足,实际未分配空间8.2G因LVM卷组名称格式差异(双破折号误写)导致无法扩展,确认正确卷组名后,使用lvextend和resize2fs... 目录1:原因2:操作3:报错5:解决问题:确认卷组名称​6:再次操作7:验证扩展是否成功8:问题已解

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空