Java虚拟机之内存分配与回收策略

Java虚拟机之内存分配与回收策略

导语:在前几篇博客中我们也特别详细的介绍了Java虚拟机的运行时数据区域和Java虚拟机的垃圾回收,我们知道在Java虚拟机中,对于内存的分配或者回收也是十分重要的,我们需要考虑在某种情况下是否内存会溢出等问题,所以本篇博客主要对于虚拟机的内存分配和回收进行讲解

首先我们先来说下什么是Minor GC和Full GC:

  • Minor GC:指发生在新生代的垃圾收集,回收新生代,因为新生代对象存活时间很短,因此Minor GC会频繁执行,执行的速度一般也会比较快
  • Full GC:回收新生代和老年代,老年代对象其存活时间很长,因此Full GC很少执行,执行速度会比Minor GC慢很多

内存分配策略

对象优先在Eden区分配

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

大对象直接进入老年代

  • 大对象是指需要连续内存空间的对象,最典型的对象是那种很长的字符串或者数组
  • 经常出现大对象会提前触发垃圾收集以获取足够的内存空间来分配给大对象
  • 虚拟机提供了一个-XX:PretenureSizeThreshold参数,大于此值的对象直接在老年代分配,避免在 Eden 和 Survivor 之间的大量内存复制

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

  • 为对象定义年龄计数器,对象在 Eden 出生并经过 Minor GC 依然存活,将移动到 Survivor 中,年龄就增加 1 岁,增加到一定年龄则移动到老年代中
  • 对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold来设置

动态对象年龄判断

  • 虚拟机并不是永远要求对象的年龄必须达到 MaxTenuringThreshold 才能晋升老年代,如果在 Survivor 中相同年龄所有对象大小的总和大于 Survivor 空间的一半,则年龄大于或等于该年龄的对象可以直接进入老年代,无需等到 MaxTenuringThreshold 中要求的年龄

空间分配担保

  • 在发生 Minor GC 之前,虚拟机先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果条件成立的话,那么 Minor GC 可以确认是安全的
  • 如果不成立的话虚拟机会查看 HandlePromotionFailure 的值是否允许担保失败,如果允许那么就会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次 Minor GC;如果小于,或者 HandlePromotionFailure 的值不允许冒险,那么就要进行一次 Full GC

Full GC的触发条件

对于Minor GC其触发条件非常简单,当Eden空间满时,就将触发一次Minor GC
而Full GC 相对于复杂,有下列条件:

调用Systm.gc()

  • 只是建议虚拟机执行 Full GC,但是虚拟机不一定真正去执行。不建议使用这种方式,而是让虚拟机管理内存

老年代空间不足

  • 老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等
  • 为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组
  • 可以通过 -Xmn 虚拟机参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代。还可以通过 -XX:MaxTenuringThreshold 调大对象进入老年代的年龄,让对象在新生代多存活一段时间

空间分配担保失败

  • 使用复制算法的 Minor GC 需要老年代的内存空间作担保,如果担保失败会执行一次 Full GC

JDK 1.7 及以前的永久代空间不足

  • 在 JDK 1.7 及以前,HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 Class 的信息、常量、静态变量等数据
  • 当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么虚拟机会抛出 java.lang.OutOfMemoryError
  • 为避免以上原因引起的 Full GC,可采用的方法为增大永久代空间或转为使用 CMS GC

Concurrent Mode Failure

  • 执行 CMS GC 的过程中同时有对象要放入老年代,而此时老年代空间不足(可能是 GC 过程中浮动垃圾过多导致暂时性的空间不足),便会报 Concurrent Mode Failure 错误,并触发 Full GC

结语:本片博客主要讲解了Java虚拟机内存分配、回收以及回收的触发条件,下篇博客将主要讲解虚拟机的类加载机制,希望大家多多关注

你可能感兴趣的:(JVM系列)