GC和对象的内存分配

昨天我们聊到了新生代、老年代,也聊到了Monitor GC,那么今天就再详细讲一下Monitor GC和Full GC、内存的分配、新生代往老年代的转移以及触发一次Monitor GC的执行流程。

1、Monitor GC和Full GC

我们先来了解一下什么是Monitor GC和Full GC:

Monitor GC

  • Monitor GC:又叫新生代GC,指发生在新生代的垃圾收集
  • 因为Java对象大都朝生息死的原因,所以新生代的Eden区内存经常会满,所以Monitor GC会特别频繁
  • Monitor GC只会清理新生代的内存,所以Monitor GC一般很快

Full GC

  • Full GC:又叫Major GC、老年代GC,指发生在老年代的垃圾收集
  • 由于老年代的对象不会新增的很频繁,所以Full GC不会太频繁
  • 发生Full GC一般都会伴随着一次Monitor GC,所以Full GC相对于Monitor GC速度会慢狠多
  • 一般一次Full GC的时间是Monitor GC时间的十倍以上

2、对象的内存分配

首先一般对象优先分配在新生代的Eden内存中。

如果对象是一个大对象(最典型的就是很长的字符串以及数组),将直接分配在老年代。这里指的大对象是基于虚拟机的一个配置-XX:PretenureSizeThreshold参数,大于这个值的对象理解为大对象。

3、对象在新生代和老年代之间的移动

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

一个刚进入新生代中的对象默认年龄是 1,每当这个对象熬过一次Monitor GC,年龄就会加 1,当对象的年龄大于-XX:MaxTenuringThreshold(默认值15)时,将被移动到老年代。

Survivor中某个年龄所占内存过大将移动部分对象到老年代

如果新生代中Survivor内存中的对象数量一直很多的话,那么Monitor GC的时候很容易发生另一块To Survivor内存不足以存储这次Monitor GC后还”存活”的对象,所以当Survivor内存中中对象大小达到一定程度之后就需要移动到老年代。

具体的判定逻辑是如果在Survivor空间中相同年龄的对象所占用的内存大小大于Survivor内存大小的一半,那么大于等于该年龄的对象将被直接移动到老年代,无需年龄等到MaxTenuringThreshold再移动。

4、一次Monitor GC的执行流程

再发生Monitor GC之前,虚拟机会检测老年代中最大可用的连续内存是否大于新生代所有对象的总空间,如果大于,那么这次Monitor一定是安全的。

如果不大于,那么虚拟机会去检测HandlePromotionFailure这个参数是否允许担保失败。

如果允许担保失败,那么虚拟机会查看老年代中最大可用的连续内存是否大于历次Monitor GC所晋升到老年代对象的平均大小,如果大于,那么将尝试进行一次Monitor GC,如果这次Monitor GC所晋升到老年代对象总大小大于老年代中最大可用的连续内存,那么Monitor GC将会失败,此时会再执行一次Gull GC。

如果小于或者HandlePromotionFailure这个参数不允许担保失败,那么将进行一次Full GC。

Monitor GC执行流程


喜欢这篇文章的朋友,欢迎扫描下图关注公众号lebronchen,第一时间收到更新内容。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/Leon_cx/article/details/81911342