内存分配与回收策略

240 阅读2分钟

对象优先在Eden分配

大多数情况下,对象会在年轻代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机会发生一次Minor GC
我们可以使用如下参数开启GC日志的输出

  • **-XX:+PrintGC  **输出GC日志
  • **-XX:+PrintGCDetails  **输出GC的详细日志
  • **-XX:+PrintGCTimeStamps  **输出GC的时间戳(以基准时间的形式)
  • **-XX:+PrintGCDateStamps  **输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)

大对象直接进入老年代

大对象是指,需要大量连续内存空间的Java对象,比如长字符串、byte[] 数组。
JVM提供了一个 **-XX:PretenureSizeThreshold **参数,令大于该值的对象直接进入老年代,避免在Eden区和Survivor区之间发生大量的内存复制。

各种GC

针对HotSpot虚拟机的实现,GC大体可以分为两类:

  • Partial GC:回收堆中某个部分的GC
    • Minor GC(Young GC):发生在年轻代的GC。
    • Mixed GC:G1收集器特有的GC,收集整个年轻代以及部分老年代的GC。
  • Full GC:针对整个新生代、老生代、元空间(metaspace,java8以上版本取代perm gen)的全局范围的GC,Full GC的速度一般会比Minor GC慢10倍以上。

回收策略

在年轻代中,除了Eden区还有From Survivor(S0)区和To Survivor(S1)区。JVM在一次Minor GC后,会将还存活的对象通过复制算法复制到Survivor区域中(S0和S1中的一个)。此时在Survivor区中的对象年龄会被标记为1,这些对象在Survivor区中每熬过一次Minor GC,年龄就+1,当年龄增长到一定阈值(默认15),就会被晋升到老年代中。晋升到老年代的阈值,可以通过参数-XX:MaxTenuringThreshold设置。
JVM并不是永远要求对象的年龄必须达到MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于等于该年龄的对象就可以直接进入老年代。