JVM垃圾收集
默认垃圾收集器
JDK1.7和JDK1.8默认垃圾收集器都是ParallelScavenge(新生代)+ParallelOld(老年代)
JDK1.9默认垃圾收集器G1
查看命令:java -XX:+PrintCommandLineFlags -version
G1
JDK 1.7推出的垃圾收集器,特点如下:
1 使用多核CPU来缩短Stop-The-World停顿的时间
2 分代收集
3 基于标记-整理算法实现,不产生空间碎片
4 建立了可预测的停顿时间模型:能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。G1把整个Java堆划分为多个大小相等的独立区域(Region),新生代和老年代不再物理隔离,都是一部分Region的集合。G1之所以能建立可预测的停顿时间模型,是因为它可以有计划地避免在整个Java堆中进行全区域的垃圾收集。
触发GC
GC有两种类型:Minor GC和Full GC。
Minor GC:当生成新对象,并且在Eden区申请空间失败时,会触发Minor GC,把存活对象复制到From Survivor区或者To Survivor区。因为Java对象大多具备朝生夕灭的特性,所以Minor GC会频繁进行。
Full GC:对整个堆进行整理,伴随至少一次的Minor GC,比Minor GC慢10倍以上。
可能导致Full GC的原因
1 老年代(Tenured)被填满
2 System.gc( )被显示调用
内存分配与回收策略
对象优先在Eden区中分配
一般对象在新生代Eden区中分配。当Eden区没有足够空间分配时,JVM发起一次Minor GC。把存活对象复制到From Surivor区。
Eden区清理后可以存放新的对象。当Eden区再次被用完,触发MinorGC,将Eden区与From Surivor区存活对象复制到To Surivor区。
下次MinorGC时,将Eden区与To Surivor区中存活对象复制到From Surivor区。
大对象直接进入老年代
大对象指需要大量连续内存空间的Java对象,例如很长的字符串和大数组。
长期存活的对象将进入老年代
JVM给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden区分配并经过第一次MinorGC后仍然存活,且能被Survivor区容纳,则将该对象移动到Survivor区,对象年龄设为1。该对象在Survivor区每熬过一次MinorGC,年龄增加1岁,当年龄增加到一定程度(默认为15岁),晋升到老年代。