理解JVM之内存分配以及分代思想实现

1.基本内存分批策略

  大多数情况在新生代Eden区分配,如果启动了本地线程分配缓冲,将按线程优先在TLAB(线程私有缓冲区)上分配.当Eden区域没有足够的空间时将发起一次Minor GC.

  值得注意的是,如果一个对象过大(例如分配了一个大的byte[]数组),该对象将直接进入老年代..因为对象过大会让新生区采用垃圾回收算法-----复制算法的效率大大降低,如果该对象存活,其会让Eden区跟两个survivor区之间发生大量的内存复制,且容易触发内存担保机制.更要命的是一个短命的对象,为了分配这个大对象花了大量的时间为他腾出空间,结果过一会就没用了,这个应该在编程时注意.

2.分代思想

  为了实现分代算法,虚拟机给每个对象定义了一个对象年龄计数器,如果该对象在Eden出生并且经过一次minor GC后仍然存活,且能被Survivor容纳,将被移动到Survivor空间中并且年龄加一,当他的年龄增加到一定程度(默认15),就会进入老年代.

  为了能够更好的适应不同程序的内存状况,虚拟机并不是永远的要求对象的年龄必须达到了年龄阈值才能进入老年代.如果Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就直接进入老年代.

3.空间分配担保

  在发生minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么本次GC是安全的.如果不成立,那么会继续检查老年代最大连续可用空间是否大于历次晋升到老年代对象的平均大小(这个平均大小实际是一种动态概率的说短),会进行一次冒险的minor GC.可设置不允许这种冒险.

ps:

  新生代GC(minor GC):指发生在新生代的垃圾收集动作,因为java对象大多都具备朝生夕灭的贴点,所以minor GC非常频繁,一般回收速度也非常快.

  老年代GC(Major GC/Ful GC):指发生在老年代的GC,出现了major GC,经常会伴随至少一次的minor GC(但不是绝对).Major GC速度一般比Minor GC慢10倍以上.

原文地址:https://www.cnblogs.com/ouhaitao/p/8582366.html