Java体系中的自动内存管理主要包括了2个方面:java
- 自动地给对象分配内存。
- 自动地回收分配给对象地内存。
大多数状况下,JVM会在 Eden
区优先分配对象,若是 Eden
没有足够的空间,则进行一次 Minor GC
。经过参数 -XX:+PrintGCDetails
可让虚拟机在进行垃圾回收时打印日志,方便咱们看到回收先后的内存占用状况。优化
例: 假如如今内存大小指定以下:spa
而后咱们又前后在代码中建立4个对象:3d
byte[] byte1 = new byte[2MB];
byte[] byte2 = new byte[2MB];
byte[] byte3 = new byte[2MB];
byte[] byte4 = new byte[4MB];
复制代码
当建立完第三个对象后,Eden区已经用掉了6M的空间来存放 byte1,byte2,byte3 三个对象,再建立第四个对象时,Eden区加上一个from区已经放不下了,如先前所述,此时会触发一次 MinorGC
,将三个2MB的对象转移到老年代中,腾出Eden区的空间给 第四个对象。日志
因此,执行后的内存状况以下:code
经过 -XX:PretentureSizeThreshold
参数设置大于这个值的对象直接分配到老年代。cdn
怎么算是长期存活 ?对象
JVM给每一个对象定义了一个 对象年龄计数器
。当对象一开始被分配到新生代Eden区,通过一次 MniorGC
后仍然存活,而且Survivor区可以容纳它,则此对象被转移到 Survivor
区,年龄变为1。
在 Survivor
区中的对象没熬过一次 MniorGC
,年龄就涨1,当年龄达到咱们设定的年龄阈值(JVM默认设定15)时,就会进入老年代。15岁就已经步入老年....
年龄阈值可经过参数 -XX:MaxTenuringThreshold = 指定值
来设定。
blog
JVM中,若是Survivor区中的相同年龄的全部对象的大小总和大于Survivor空间的一半,那么这些同学们就直接进入老年代。无须等到上面的年龄阈值。
首先介绍一下 Mnior GC
和 Full GC
的区别:
MniorGC : 发生在新生代的垃圾回收活动,因为新生代的Java对象 短命的特性,这种垃圾回收活动频繁,回收速度较快。(就像扫碎纸屑) Full GC : 发生在老年的垃圾回收活动,不过出现一次 Full GC,也会伴随着一次 MniorGC,因为老年代中的对象基本都是大对象,长命,因此Full GC的速度比Mnior GC 的速度慢10倍以上。(就像搬大石头)
新生代的垃圾回收算法采用的是 复制算法 ,当进行一次 Mnior GC
时,会将新生代的活动区域( Eden区
和Survivor中的 From区
)中的存活对象复制到 Survivor中的 to区
,若是 to 区的内存不足以放下这些对象,那么这时就须要老年代出马,进行分配担保机制,将放不下的对象放到老年代。
因此,在进行 Monior GC
前,JVM会作如下流程的检查,以确认老年代是否可以放得下那些对象,来选择进行 Mnior GC
仍是 Full GC
。
Reference:
深刻理解Java虚拟机