JVM内存池

JVM内存池

JVM共享内存区域或者叫内存池方法区或者称为永久代(Permgen)两块,其中堆内存分为年轻代(Young)老年代(Tenured),而年轻代又被划分为三个区域Eden、Survivor 1、Survivor 2
JVM内存池

Eden空间

对象被创建时通常被分配到Eden空间。为了解决对象分配内存时的线程安全问题,为每个线程在Eden空间中预先分配一小块内存TLAB(本地线程分配缓冲),线程给对像分配内存时在TLAB上分配,当TLAB中没有足够的内存时会将数据同步到Common Area中,如果Common Area中也没有足够的内存那么Minor GC将会被触发释放内存空间,如果任然没有足够的内存对象将会被直接通过分配担保机制进入老年代。

Eden空间

是否使用TLAB可以通过-XX:+/-UseTLAB参数来控制。

Survivor空间

当每次Minor GC时JVM会将还存活的对象进行标记标记完成后在Eden空间和From Survivor空间中所有存活的对象将会被复制到To Survivor空间中,当然第一次Minor GC时From Survivor应该是空的,之后To Survivor空间和From Survivor空间角色互换,该过程就是使用的复制算法。在对象头中的运行时数据中存放了对象的GC分代年龄,每一次对象从GC中存活下来后都将会对GC分代年龄加一,当GC分代年龄超过一定的阈值时,该对象将会将不会复制到To Survivor空间中而是直接复制到Tenured(老年代)中,直到该对象变为不可达被回收。

Survivor空间

JVM内存池实际工作监控情况

由于我的JDK是1.8所以该图中显示是的Mataspace空间,如果是用的JDK1.7该处应该是PermGen。

由此图可以明显的看出每当一个Eden空间达到某个值时,就会触发一次GC将Eden空间中的部分存活对象复制到To Survivor中,并将Eden清空。还可以明显的看出Survivor 1 和 Survivor 2 是交替作为From Survivor和To Survivor空间角色。

内存池实际工作监控图

HotSpot虚拟机默认Eden:From Survivor:To Survivor的大小比例是8:1:1
实际的阈值可以通过JVM参数-XX:MaxTenuringThreshold动态指定HotSpot中默认的阀值为15个GC周期