【JVM】【第六章】【JVM 运行时数据区】【堆】【02】对象分配过程

1.对象分配难点

  • 为新对象分配内存是一件非常严谨和复杂的任务,JVM的设计者们不仅需要考虑内存如何分配、在哪里分配等问题,并且由于内存分配算法与内存回收算法密切相关,所以还需要考虑GC执行完内存回收后是否会在内存空间中产生内存碎片。

2.图解对象分配过程

  1. 起初创建对象,对象都分配在Eden区,此区有大小限制。

  2. 当Eden区满了,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Young/Minor GC),GC会导致用户线程阻塞,在此期间JVM将伊甸园区中的不再被其他对象所引用的对象进行销毁,并且将Eden区中存活的对象移动到其中一个Survivor区,GC结束后,再加载新的对象时,将其放到Eden区
    在这里插入图片描述
    补充说明:
    图中绿色的是存活的,GC后仍然存活的,会被放进其中一个Survivor from区
    每个对象都会有年龄计数器,每发生一次GC,存活下来的话都会加一。

  3. Eden区继续存放对象,当Eden区再次存满的时候,又会触发一个MinorGC操作;此时GC将会把 Eden和Survivor From中的对象进行一次垃圾收集,把存活的对象放到 Survivor To区,同时让存活的对象年龄 + 1
    在这里插入图片描述
    补充说明:
    Survivor from 区和 Survivor to区依次交换。复制之后有交换,谁空谁是to。

  4. 年龄等于15的(经过15次minor GC的)对象,再次发生GC时就会被移动到养老区;没有15的仍然在survivor两个区中轮转
    在这里插入图片描述
    我们继续不断的进行对象生成和垃圾回收,当Survivor中的对象的年龄达到15的时候,将会触发一次 Promotion 晋升的操作,也就是将年轻代中的对象晋升到老年代中


3.额外补充

(1) 进入老年代的阈值
默认超过15次,就会移动到养老区。
可以使用 -XX:MaxTenuringThreshold= 参数进行设置。

(2) Minor GC触发机制
注意:只有Eden满了才会触minorGC/youngGC,而幸存者区满了是绝对不会触发minorGC的。

(3) Major GC 和 OOM
在养老区,相对悠闲。当老年区内存不足时,再次触发GC:Major GC,进行养老区的内存清理。若养老区执行了Major GC之后发现依然无法进行对象的保存,就会产生OOM异常。

(4) 关于垃圾回收
频繁在新生区收集,很少在养老区收集,几乎不在永久区/元空间收集。

(5) 进入老年代有两种方式

  • 一种是年纪到达阈值。
  • 另一种是在年轻代满了,仍然添加对象的时候,会有老年代担保,直接进入老年代。

4.对象分配的特殊情况

在这里插入图片描述

特殊情况1:S区无法存放下存活对象

  • 如果 Eden 区满了,在Minor GC的过程中,会判断S区能不能放的下存活的对象,放得下就将对象往幸存区拷贝,发现幸存区放不下啦,那只能便宜了某些新对象,让他们直接晋升至老年区

特殊情况2:超大对象

  • 当来了一个新对象申请堆内存,Eden区存放不下,发生MinorGC,此时Eden区会被清空;Minor GC后,如果Eden区仍然放不下这个对象,说明这个对象是一个超大对象,此时只能直接放进老年代;
  • 当老年代都放不下了,则先触发Full GC ,再看看能不能放下但如果还是放不下,那只能报 OOM 啦~~~

5.代码演示对象分配过程

在这里插入图片描述

在这里插入图片描述
当老年代放不下了就oom了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值