天天看点

分代收集算法

分代收集算法是JVM垃圾回收的机制,其实是【简单了解常见的GC算法】的综合应用。JVM的堆中存在许多对象,根据这些对象的生命周期(存活时间)可以将内存分为几个部分,eg:堆上的新生代和老年代,方法区的永久代。每个部分使用不同的GC算法进行垃圾回收,这就是分代收集算法。

新生代

顾名思义,新生代指新建对象存放的地方。一般来说,新建对象存放在新生代中,eg:局部变量。java程序中,90%以上的对象都是生命周期较短的,换句话说,90%以上的对象在新生代就回被回收掉。从前面文章可以知道,复制算法是非常适合这个场景的。新生代中分为3部分,1个eden区和2个survivor区(survivor0和survivor1),默认情况下,eden区与survivor区的比例为8:1:1。

复制算法的过程:程序创建对象发现eden区内存不够时,JVM的垃圾回收器将对eden区进行垃圾回收(Minor GC),将eden区中的不可回收的对象复制到survivor0区。如果survivor0区内存不够,则将survivor0区中不可回收的对象复制到survivor1区,然后将eden区和survivor0区中所有对象回收。

【JVM堆中的配置参数】

老年代

在新生代survivor区中生命周期足够久的对象将会晋升到老年代中,eg:缓存。生命周期足够久的概念:默认情况下经历了15次GC,或者超过-XX:MaxTenuringThreshold参数配置的次数;除此以外,如果对象需要的空间比较大,超出了eden区+1个survivor区的大小,或者超过-XX:PreternureSizeThreshold参数的值,也会直接进入老年代。一般来说,老年代内存空间比新生代大(默认老年代:新生代为1:2),老年代内存满后触发Full GC,使用标记-整理算法进行垃圾回收。Full GC花费的时间远长于Minor GC。

-Xmx40M -Xms40M -Xmn10M -XX:+PrintGCDetails

package com.su.mybatis.oracle.controller;

public class Test {

    public static void main(String[] args) {
        byte[] b = new byte[1024 * 1024 * 9 + 1];
    }
}
           

输出结果:

Heap
 def new generation   total 9216K, used 876K [0x31d00000, 0x32700000, 0x32700000)
  eden space 8192K,  10% used [0x31d00000, 0x31ddb148, 0x32500000)
  from space 1024K,   0% used [0x32500000, 0x32500000, 0x32600000)
  to   space 1024K,   0% used [0x32600000, 0x32600000, 0x32700000)
 tenured generation   total 30720K, used 9216K [0x32700000, 0x34500000, 0x34500000)
   the space 30720K,  30% used [0x32700000, 0x33000010, 0x33000200, 0x34500000)
 compacting perm gen  total 12288K, used 153K [0x34500000, 0x35100000, 0x38500000)
   the space 12288K,   1% used [0x34500000, 0x345266f8, 0x34526800, 0x35100000)
    ro space 10240K,  44% used [0x38500000, 0x38977808, 0x38977a00, 0x38f00000)
    rw space 12288K,  52% used [0x38f00000, 0x3954e610, 0x3954e800, 0x39b00000)
           

永久代

永久代指方法区,存放类、静态变量、常量等,发生垃圾回收较少,当永久代中内存不足时,触发Full GC。

如果有写的不对的地方,请大家多多批评指正,非常感谢!

jvm