JVM对象内存分配机制之对象在Eden区分配

  • 前言
  • 一、对象在Eden区分配
  • 二、大对象直接进入老年代
  • 三、长期存活的对象将进入老年代
  • 四、老年代空间分配担保机制

前言

上篇文章解释了对象在栈上分配的相关内容,这篇是上一篇的后续,解释一下对象在Eden区分配,以及上一篇内存分配流程图中大对象和长期存活的对象该何去何从。


一、对象在Eden区分配

大多数情况下,对象在新生代中 Eden 区分配。当 Eden 区没有足够空间进行分配时,虚拟机将发起一次Minor GC。我 们来进行实际测试一下。

在测试之前我们先来看看 Minor GC和Full GC 有什么不同呢?

Minor GC/Young GC:指发生新生代的的垃圾收集动作,Minor GC非常频繁,回收速度一般也比较快。

Major GC/Full GC:一般会回收老年代 ,年轻代,方法区的垃圾,Major GC的速度一般会比Minor GC的慢 10倍以上。

Eden与Survivor区默认8:1:1

大量的对象被分配在eden区,eden区满了后会触发minor gc,可能会有99%以上的对象成为垃圾被回收掉,剩余存活 的对象会被挪到为空的那块survivor区,下一次eden区满了后又会触发minor gc,把eden区和survivor区垃圾对象回 收,把剩余存活的对象一次性挪动到另外一块为空的survivor区,因为新生代的对象都是朝生夕死的,存活时间很短,所 以JVM默认的8:1:1的比例是很合适的,让eden区尽量的大,survivor区够用即可, JVM默认有这个参数-XX:+UseAdaptiveSizePolicy(默认开启),会导致这个8:1:1比例自动变化,如果不想这个比例有变 化可以设置参数-XX:-UseAdaptiveSizePolicy

package com.daydayup.jvm;/*** 添加运行JVM参数:-XX:+PrintGCDetails*/
public class GCTest {public static void main(String[] args) throws InterruptedException {byte[] allocation1, allocation2/*, allocation3, allocation4, allocation5, allocation6*/;allocation1 = new byte[60000*1024];
//        allocation2 = new byte[8000*1024];
//         allocation3 = new byte[1000*1024];
//         allocation4 = new byte[1000*1024];
//         allocation5 = new byte[1000*1024];
//         allocation6 = new byte[1000*1024];}
}
//运行结果[GC (Allocation Failure) [PSYoungGen: 65024K->904K(75776K)] 65024K->912K(249344K), 0.0006997 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
HeapPSYoungGen      total 75776K, used 2204K [0x000000076bd00000, 0x0000000771180000, 0x00000007c0000000)eden space 65024K, 2% used [0x000000076bd00000,0x000000076be45378,0x000000076fc80000)from space 10752K, 8% used [0x000000076fc80000,0x000000076fd62020,0x0000000770700000)to   space 10752K, 0% used [0x0000000770700000,0x0000000770700000,0x0000000771180000)ParOldGen       total 173568K, used 8K [0x00000006c3600000, 0x00000006cdf80000, 0x000000076bd00000)object space 173568K, 0% used [0x00000006c3600000,0x00000006c3602000,0x00000006cdf80000)Metaspace       used 3221K, capacity 4496K, committed 4864K, reserved 1056768Kclass space    used 350K, capacity 388K, committed 512K, reserved 1048576K

我们可以看出eden区内存几乎已经被分配完全(即使程序什么也不做,新生代也会使用至少几M内存)。假如我们再为 allocation2分配内存会出现什么情况呢?

package com.daydayup.jvm;/*** 添加运行JVM参数:-XX:+PrintGCDetails*/
public class GCTest {public static void main(String[] args) throws InterruptedException {byte[] allocation1, allocation2/*, allocation3, allocation4, allocation5, allocation6*/;allocation1 = new byte[60000*1024];allocation2 = new byte[8000*1024];
//         allocation3 = new byte[1000*1024];
//         allocation4 = new byte[1000*1024];
//         allocation5 = new byte[1000*1024];
//         allocation6 = new byte[1000*1024];}
}//运行结果[GC (Allocation Failure) [PSYoungGen: 65024K->920K(75776K)] 65024K->60928K(249344K), 0.0243280 secs] [Times: user=0.14 sys=0.00, real=0.02 secs]
HeapPSYoungGen      total 75776K, used 9570K [0x000000076bd00000, 0x0000000775100000, 0x00000007c0000000)eden space 65024K, 13% used [0x000000076bd00000,0x000000076c572a78,0x000000076fc80000)from space 10752K, 8% used [0x000000076fc80000,0x000000076fd66030,0x0000000770700000)to   space 10752K, 0% used [0x0000000774680000,0x0000000774680000,0x0000000775100000)ParOldGen       total 173568K, used 60008K [0x00000006c3600000, 0x00000006cdf80000, 0x000000076bd00000)object space 173568K, 34% used [0x00000006c3600000,0x00000006c709a010,0x00000006cdf80000)Metaspace       used 3221K, capacity 4496K, committed 4864K, reserved 1056768Kclass space    used 350K, capacity 388K, committed 512K, reserved 1048576K

简单解释一下为什么会出现这种情况: 因为给allocation2分配内存的时候eden区内存几乎已经被分配完了,我们刚刚讲 了当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC,GC期间虚拟机又发现allocation1无法存入 Survior空间,所以只好把新生代的对象提前转移到老年代中去,老年代上的空间足够存放allocation1,所以不会出现 Full GC。执行Minor GC后,后面分配的对象如果能够存在eden区的话,还是会在eden区分配内存。

package com.daydayup.jvm;/*** 添加运行JVM参数:-XX:+PrintGCDetails*/
public class GCTest {public static void main(String[] args) throws InterruptedException {byte[] allocation1, allocation2, allocation3, allocation4, allocation5, allocation6;allocation1 = new byte[60000*1024];allocation2 = new byte[8000*1024];allocation3 = new byte[1000*1024];allocation4 = new byte[1000*1024];allocation5 = new byte[1000*1024];allocation6 = new byte[1000*1024];}
}//运行结果[GC (Allocation Failure) [PSYoungGen: 65024K->872K(75776K)] 65024K->60880K(249344K), 0.0233776 secs] [Times: user=0.00 sys=0.02, real=0.02 secs]
HeapPSYoungGen      total 75776K, used 13785K [0x000000076bd00000, 0x0000000775100000, 0x00000007c0000000)eden space 65024K, 19% used [0x000000076bd00000,0x000000076c99c798,0x000000076fc80000)from space 10752K, 8% used [0x000000076fc80000,0x000000076fd5a020,0x0000000770700000)to   space 10752K, 0% used [0x0000000774680000,0x0000000774680000,0x0000000775100000)ParOldGen       total 173568K, used 60008K [0x00000006c3600000, 0x00000006cdf80000, 0x000000076bd00000)object space 173568K, 34% used [0x00000006c3600000,0x00000006c709a010,0x00000006cdf80000)Metaspace       used 3221K, capacity 4496K, committed 4864K, reserved 1056768Kclass space    used 350K, capacity 388K, committed 512K, reserved 1048576K

二、大对象直接进入老年代

大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。JVM参数 -XX:PretenureSizeThreshold 可以设置大对象的大小,如果对象超过设置大小会直接进入老年代,不会进入年轻代,这个参数只在 Serial 和ParNew两个收集器下 有效。比如设置JVM参数:-XX:PretenureSizeThreshold=1000000 (单位是字节) -XX:+UseSerialGC ,再执行下上面的第一 个程序会发现大对象直接进了老年代 。

原因是为了避免为大对象分配内存时的复制操作而降低效率。

三、长期存活的对象将进入老年代

既然虚拟机采用了分代收集的思想来管理内存,那么内存回收时就必须能识别哪些对象应放在新生代,哪些对象应放在 老年代中。为了做到这一点,虚拟机给每个对象一个对象年龄(Age)计数器。
如果对象在 Eden 出生并经过第一次 Minor GC 后仍然能够存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为1。对象在 Survivor 中每熬过一次 MinorGC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁,CMS收集器默认6岁,不同的垃圾收集器会略微有点不同),就会被晋升到老年代中。对象晋升到老年代 的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置。

四、老年代空间分配担保机制

年轻代每次minor gc之前JVM都会计算下老年代剩余可用空间 ,如果这个可用空间小于年轻代里现有的所有对象大小之和(包括垃圾对象) 就会看一个“-XX:-HandlePromotionFailure”(jdk1.8默认就设置了)的参数是否设置了, 如果有这个参数,就会看看老年代的可用内存大小,是否大于之前每一次minor gc后进入老年代的对象的平均大小

如果上一步结果是小于或者之前说的参数没有设置,那么就会触发一次Full gc,对老年代和年轻代一起回收一次垃圾, 如果回收完还是没有足够空间存放新的对象就会发生"OOM" 当然,如果minor gc之后剩余存活的需要挪动到老年代的对象大小还是大于老年代可用空间,那么也会触发full gc,full gc完之后如果还是没有空间放minor gc之后的存活对象,则也会发生“OOM”。

下面附担保机制的流程图:

JVM对象内存分配机制之对象在Eden区分配(五)相关推荐

  1. JVM的内存管理机制详解

    一.为什么要学习内存管理? Java与C++之间有一堵由内存动态分配和垃圾回收机制所围成的高墙,墙外面的人想进去,墙里面的人出不来 对于Java程序员来说,JVM给我们提供了自动内存管理机制,不需要既 ...

  2. 对象在Eden区分配

    一.对象在Eden区分配 大多数情况下,对象在新生代中 Eden 区分配.当 Eden 区没有足够空间进行分配时,虚拟机将发起一次Minor GC. 在测试之前我们先来看看 Minor GC和Full ...

  3. JVM学习笔记-GC日志分析(对象优先在Eden区分配)

    前言 在进行GC日志分析前,先了解一下JVM虚拟机运行时数据区的主要划分: Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域 有各自的用途,以及创建和销毁 ...

  4. JVM自动内存管理机制——Java内存区域(下)

    一.虚拟机参数配置 在上一篇<Java自动内存管理机制--Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...

  5. Java技术专题之JVM逻辑内存回收机制研究图解版

    一.引言 JVM虚拟机内存回收机曾迷惑了不少人,文本从JVM实现机制的角度揭示JVM内存回收的原理和机制. 一.Java平台逻辑架构 二.JVM物理结构 通过从JVM物理结构图我们可以看到: 1.JV ...

  6. eden区分配至s0、s1

    1.eden如何分配给s0.s1 由此图看出,eden区做第一次YGC时,放入s0.s1时是随机的.这里存在一个from和to的概念,from是接收从eden区来YGC对象,to是由from占满时时转 ...

  7. oracle 区分配,ORACLE自动段管理的区分配大小测试

    说明:大家知道ORACLE表空间的最小分配单元是区,当进行文件空间划分的时候每次增加的大小都是按区来进行的,且ORACLE在创建表空间的时候,关于EXTENT MANAGEMENT的管理会有两个选项: ...

  8. JAVA入门级教学之(关于JVM的内存管理机制)

  9. JVM——对象创建与内存分配机制

    文章目录 1.对象的创建 1.1.类加载检查 1.2.分配内存 1.3.初始化 1.4.设置对象头 1.5.执行方法 2.对象内存分配 2.1. 对象栈上分配 2.2.对象在Eden区分配 2.3.大 ...

  10. JVM的内存分配与回收策略实战——对象优先在Eden分配

    本文代码在测试时使用的垃圾收集器组合是Serial/Serial Old. 这里还需要介绍一些JVM的基本参数,本文中进行如下设置: -verbose gc 打印垃圾收集信息 -Xms20M 堆容量设 ...

最新文章

  1. osi 模型 tcpip网络模型
  2. 超越时代的天才——图灵
  3. 牛客华为机试第1题python
  4. c语言从键盘输入千米数,第二章 C语言编程基础.ppt
  5. 一步一步学Silverlight 2系列(5):实现简单的拖放功能
  6. jersey spring_实施Jersey 2 Spring集成
  7. 伙伴分配器的一个极简实现
  8. 6种不同画法画平行线_今年超火的Prada Hobo,原来有6种不同
  9. HDU2030 汉字统计【入门】
  10. Day_05显示变量的值
  11. 数据分析~中国五大城市PM2.5数据分析01
  12. CDR类CAD制作室内装修平面图
  13. P1179 [NOIP2010 普及组] 数字统计
  14. 计算机助理职称考试成绩查询,初级成绩可以查询了!
  15. 关于XMLHttpRequest的xhr.readyState和 xhr.status 的简单使用
  16. Python调用WPS进行文档转换PDF及PDF转图片
  17. prim algorithm
  18. InceptionV3实战:tensorflow2.X版本,InceptionV3图像分类任务(大数据集)
  19. lg空调代码大全解决_lg空调故障代码是什么意思 lg空调故障代码大全【详解】...
  20. oracle 云服务免费申请

热门文章

  1. 在php中使用for、while、do-while循环实现从1加到100
  2. 课程设计(飞机订票系统) 超全
  3. SQL注入原理,啊D明小子高手必看! 明小子4.1我已上传 可以下载
  4. XX数据中心技术方案
  5. lightroom classic破解版
  6. 谷歌离线地图二次开发源代码
  7. php9.0论坛搭建默认,phpwind9.0
  8. 生产计划管理系统实现生产计划流程完美结合
  9. 时钟转盘html源代码
  10. 一个门外汉的产品设计漫谈