2、垃圾回收算法
1)标记清除
定义:Mark Sweep
优点:速度较快
缺点:会产生内存碎片
2)标记整理
Mark Compact
特点
速度慢
没有内存碎片
3)复制
Copy
分成两片大小相同的内存区域。
不会有内存碎片
需要占用两倍内存空间
3、分代垃圾回收
新创建的对象首先分配在 eden 区。
新生代空间不足时,触发minor gc,eden区和From区存活的对象使用-copy复制到幸存区To中,存活的对象年龄加1,然后交换From 和To的区域。
minor gc 会引发 stop the world,暂停其他线程,等垃圾回收结束后,恢复用户线程运行。
因为在MGC的时候,对象地址可能会变,如果不停止其他线程的话,其他线程还引用了某些对象地址,会出现异常。
当幸存区对象的寿命超过阈值时,会晋升到老年代,最大的寿命是 15(4bit)。
当老年代空间不足时,会先触发 minor gc,如果空间仍然不足,那么就触发 full fc ,停止的时间更长。
1)相关 JVM 参数
含义 | 参数 |
---|---|
堆初始大小 | -Xms |
堆最大大小 | -Xmx 或 -XX:MaxHeapSize=size |
新生代大小 | -Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size ) |
幸存区比例(动态) | -XX:InitialSurvivorRatio=ratio 和 -XX:+UseAdaptiveSizePolicy |
幸存区比例 | -XX:SurvivorRatio=ratio |
晋升阈值 | -XX:MaxTenuringThreshold=threshold |
晋升详情 | -XX:+PrintTenuringDistribution |
GC详情 | -XX:+PrintGCDetails -verbose:gc |
FullGC 前 MinorGC | -XX:+ScavengeBeforeFullGC |
2)GC 分析
public class Code_10_GCTest {
private static final int _512KB = 512 * 1024;
private static final int _1MB = 1024 * 1024;
private static final int _6MB = 6 * 1024 * 1024;
private static final int _7MB = 7 * 1024 * 1024;
private static final int _8MB = 8 * 1024 * 1024;
// -Xms20m -Xmx20m -Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
list.add(new byte[_6MB]);
list.add(new byte[_512KB]);
list.add(new byte[_6MB]);
list.add(new byte[_512KB]);
list.add(new byte[_6MB]);
}
}
通过上面的代码,给 list 分配内存,来观察 新生代和老年代的情况,什么时候触发 minor gc,什么时候触发 full gc 等情况,使用前需要设置 jvm 参数。