jvm - 内存空间提到了,创建对象的时候,对象是在堆内存中创立的。但堆内存又分为新生代和老年代,新生代又细分Eden空间、From Survivor空间、To Survivor空间。咱们创立的类到底在哪里?

对象优先在Eden调配

堆内存分为新生代和老年代,新生代是用于寄存应用后筹备被回收的对象,老年代是用于寄存生命周期比拟长的对象。大部分咱们创立的对象,都属于生命周期比拟短的,所以会寄存在新生代。新生代又细分Eden空间、From Survivor空间、To Survivor空间,咱们创立的对象,对象优先在Eden调配。

随着对象的创立,Eden残余内存空间越来越少,就会触发Minor GC,于是Eden的存活对象会放入From Survivor空间。

Minor GC后,新对象仍然会往Eden调配。

Eden残余内存空间越来越少,又会触发Minor GC,于是Eden和From Survivor的存活对象会放入To Survivor空间。

大对象间接进入老年代

在下面的流程中,如果一个对象很大,始终在Survivor空间复制来复制去,那很费性能,所以这些大对象间接进入老年代。能够用XX:PretenureSizeThreshold来设置这些大对象的阈值。

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

在下面的流程中,如果一个对象Hello_A,曾经经验了15次Minor GC还存活在Survivor空间中,那他行将转移到老年代。这个15能够通过-XX:MaxTenuringThreshold来设置的,默认是15。虚拟机为了给对象计算他到底经验了几次Minor GC,会给每个对象定义了一个对象年龄计数器。如果对象在Eden中通过第一次Minor GC后依然存活,挪动到Survivor空间年龄加1,在Survivor区中每经验过Minor GC后依然存活年龄再加1。年龄到了15,就到了老年代。

动静年龄判断

除了年龄达到MaxTenuringThreshold的值,还有另外一个形式进入老年代,那就是动静年龄判断:在Survivor空间中雷同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就能够间接进入老年代。
比方Survivor是100M,Hello1和Hello2都是3岁,且总和超过了50M,Hello3是4岁,这个时候,这三个对象都将到老年代。

空间调配担保

下面的流程提过,存活的对象都会放入另外一个Survivor空间,如果这些存活的对象比Survivor空间还大呢?整个流程如下:

  1. Minor GC之前,虚构机会先查看老年代最大可用的间断空间是否大于新生代所有对象总空间,如果大于,则发动Minor GC。
  2. 如果小于,则看HandlePromotionFailure有没有设置,如果没有设置,就发动full gc。
  3. 如果设置了HandlePromotionFailure,则看老年代最大可用的间断空间是否大于历次降职到老年代对象的均匀大小,如果小于,就发动full gc。
  4. 如果大于,发动Minor GC。Minor GC后,看Survivor空间是否足够寄存存活对象,如果不够,就放入老年代,如果够放,就间接寄存Survivor空间。如果老年代都不够放存活对象,担保失败(Handle Promotion Failure),发动full gc。