JVM 年轻代 老年代 持久代 GC

  • Post author:
  • Post category:其他




虚拟机中的共划分为三个代:年轻代(


Young Generation


)、年老点(


Old Generation


)和持久代(


Permanent Generation


)。其中持久代主要存放的是


Java


类的类信息,与垃圾收集要收集的


Java


对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。



年轻代




:




所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区。一个


Eden


区,两个


Survivor





(


一般而言


)


。大部分对象在


Eden


区中生成。当


Eden


区满时,还存活的对象将被复制到


Survivor


区(两个中的一个),当这个


Survivor


区满时,此区的存活对象将被复制到另外一个


Survivor


区,当这个


Survivor


去也满了的时候,从第一个


Survivor


区复制过来的并且此时还存活的对象,将被复制“年老区


(Tenured)”


。需要注意,


Survivor


的两个区是对称的,没先后关系,所以同一个区中可能同时存在从


Eden


复制过来 对象,和从前一个


Survivor


复制过来的对象,而复制到年老区的只有从第一个


Survivor


去过来的对象。而且,


Survivor


区总有一个是空的。同时,根据程序需要,


Survivor


区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。



年老代




:




在年轻代中经历了


N


次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。



持久代




:




用于存放静态文件,如今


Java


类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些


class


,例如


Hibernate


等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过





XX:MaxPermSize


=<N>


进行设置。





Scavenge GC




一般情况下,当新对象生成,并且在


Eden


申请空间失败时,就会触发


Scavenge GC


,对


Eden


区域进行


GC


,清除非存活对象,并且把尚且存活的对象移动到


Survivor


区。然后整理


Survivor


的两个区。这种方式的


GC


是对年轻代的


Eden


区进行,不会影响到年老代。因为大部分对象都是从


Eden


区开始的,同时


Eden


区不会分配的很大,所以


Eden


区的


GC


会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使


Eden


去能尽快空闲出来。



Full GC




对整个堆进行整理,包括


Young





Tenured





Perm





Full GC


因为需要对整个对进行回收,所以比


Scavenge GC


要慢,因此应该尽可能减少


Full GC


的次数。在对


JVM


调优的过程中,很大一部分工作就是对于


FullGC


的调节。有如下原因可能导致


Full GC




·


年老代(


Tenured


)被写满


·


持久代(


Perm


)被写满


·


System.gc


()


被显示调用


·


上一次


GC


之后


Heap


的各域分配策略动态变化