虚拟机中的共划分为三个代
年轻代(Young Generation)、老年代(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。
分代回收器有两个分区
年轻代和老年代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。
年轻代:所有新生成的对象都是放在年轻代中,目的是为了快速回收掉那些生命周期较短的对象。
年轻代分为三个区 一个Eden(伊甸园)区和两个Survivor(From、To)区,默认三者比例8:1:1。
工作流程:为对象分配内存的时候,首先使用Eden空间,发生GC后,新生代使用的是复制算法,它的执行流程如下: 把 Eden + From Survivor 存活的对象放入 To Survivor 区; 清空 Eden 和 From Survivor 分区; From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。 每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年 龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。
新生代系统利用率:因为在进行GC的时候,总有一个survivor被清空保持空闲状态,因此新生代的内存利用率最大为90%。
老生代:当空间占用到达某个值之后就会触发全局垃圾收回,一般使用标记整理的 执行算法。以上这些循环往复就构成了整个分代垃圾回收的整体执行流程。
GC触发条件
Minor GC触发条件:
- Eden区满时
Full GC触发条件:
- 调用System.gc时,系统建议执行Full GC,但是不必然执行
- 老年代空间不足
- 方法区空间不足
- 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
- 由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小。
对象进入老年代的三种情况
- 假如进行Minor GC时发现,存活的对象在ToSpace区中存不下,那么把存活的对象存入老年代
- 假设新创建的对象很大,比如为5M(这个值可以通过PretenureSizeThreshold这个参数进行设置,默认3M),那么即使Eden区有足够的空间来存放,也不会存放在Eden区,而是直接存入老年代
- 长期存活的对象将进入老年代(对象年龄超过15岁,默认15)