虚拟机中的共划分为三个代:
年轻代(Young Generation)
年老点(Old Generation)
持久代(Permanent Generation)
其中持久代主要存放的是 Java 类的类信息, 与垃圾收集要收集的 Java 对象关系不大. 年轻代和年老代的划分是对垃圾收集影响比较大的.
1, 年轻代:
所有新生成的对象首先都是放在年轻代的. 年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象. 年轻代分三个区. 一个 Eden 区, 两个 Survivor 区(一般而言). 大部分对象在 Eden 区中生成. 当 Eden 区满时, 还存活的对象将被复制到 Survivor 区(两个的一个), 当这个 Survivor 区满时, 此区的存活对象将被复制到另外一个 Survivor 区, 当这个 Survivor 去也满了的时候, 从第一 Survivor 区复制过来的并且此时还存活的对象, 将被复制 "年老区(Tenured)". 需要注意, Survivor 的两个区是对称的, 没先后系, 所以同一个区中可能同时存在从 Eden 复制过来 对象, 和从前一个 Survivor 复制过来的对象, 而复制到年老区的只有从第一个 Survivor 去过来的对象. 而且, Survivor 区总有一个是空的. 同时, 根据程序需要, Survivor 区是可以配置为多个的(多于两个), 这样可以增加对象在年轻代中的存在时间, 减少被放到年老代的可能.
2, 年老代:
在年轻代中经历了 N 次垃圾回收后仍然存活的对象, 就会被放到年老代中. 因此, 可以认为年老代中存放的都是一些生命周期较长的对象.
3, 持久代:
用于存放静态文件, 如今 Java 类, 方法等. 持久代对垃圾回收没有显著影响, 但是有些应用可能动态生成或者调用一些 class, 例 Hibernate 等, 在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类. 持久代大小通过 - XX:MaxPermSize=<N > 进行设置.
什么情况下触发垃圾回收
由于对象进行了分代处理, 因此垃圾回收区域, 时间也不一样. GC 有两种类型: Scavenge GC 和 Full GC.
Scavenge GC
一般情况下, 当新对象生成, 并且在 Eden 申请空间失败时, 就会触发 Scavenge GC, 对 Eden 区域进行 GC, 清除非存活对象, 并且把尚且存活的对象移动到 Survivor 区. 然后整理 Survivor 的两个区. 这种方式的 GC 是对年轻代的 Eden 区进行, 不会影响到年老代因为大部分对象都是从 Eden 区开始的, 同时 Eden 区不会分配的很大, 所以 Eden 区的 GC 会频繁进行. 因而, 一般在这里需要使用速度快, 效率高的算法, 使 Eden 去能尽快空闲出来.
Full GC
对整个堆进行整理, 包括 Young,Tenured 和 Perm.Full GC 因为需要对整个对进行回收, 所以比 ScavengeGC 要慢, 因此应该尽可能减少 Full GC 的次数. 在对 JVM 调优的过程中, 很大一部分工作就是对于 FullGC 的调节.
有如下原因可能导致 Full GC:
. 年老代 (Tenured) 被写满
. 持久代 (Perm) 被写满
. System.gc()被显示调用
来源: https://www.cnblogs.com/lemon-flm/p/10191000.html