案例
家喻户晓,GC 次要回收的是堆内存,堆内存中蕴含年老代和老年代,年老代分为 Eden 和 Surivor,如下图所示。咱们用案例剖析下堆的 GC 信息【版本:HotSpot JDK1.8】。
/**
* @author:jiaolian
* @date:Created in 2021-03-15 15:02
* @description:新生代内存测试
* @modified By:* 公众号: 叫练
*/
public class NewGenTest {public static void main(String[] args) {
// 每次在 Eden 申请 1M 空间
byte[] bytes = null;
for (int i=0; i<5; i++) {bytes = new byte[1024*1024];
}
}
}
案例很简略,for 循环运行 5 次,每次在 Eden 申请 1M 空间,假如咱们调配堆内存空间是 20m,并打印 GC 详细信息,配置过程:-XX:+PrintGCDetails -Xmx20m。
- -XX:+PrintGCDetails:打印 GC 详细信息。
- -Xmx20m:调配最大堆内存空间是 20m。
GC 详细分析
运行程序,IDEA 控制台打印后果如下:
- 第一句话:年老代 GC 了一次,因为第五次循环,Eden 满了,年老代内存约 6M(6144K),Eden 回收前约 5M(5057K), 回收后是 489K,年老代内存回收前约是 5M,回收后约是 2M(1783K), 总堆内存大小约是 20M(19968K),GC 耗时 0.0016002 secs。
- 第二句话:年老代总内存约 6M,应用约 5M。
- 第三句话:eden 空间总内存约 5M(5632K),使用率是 94%。
- 第四句话:from 是 512K,使用率是 95%。
- 第五句话:老年代总空间约 14M(13824K),应用了 1294K,这个应用空间是因为程序在 Eden 申请 1M 空间,判断空间不够,就申请 from 或者 to 空间,发现只有 512K,就触发 monitor GC,将 1M 内存申请在老年代。
- 第六句话:元空间内存。
- -Xms 初始堆大小,不够时,会主动扩大,所以个别 Xms 空间和Xmx 最大堆空间 设置成一样的。
下面程序不变,设置 JVM 参数,-XX:+PrintGCDetails -Xmx20m -Xms5m,运行程序,局部后果如下图所示。
如上图所示:初始化堆大小是 5M,新生代内存一共产生了 4 次 GC,从上图能够剖析,Eden 只有 1M 多内存能够被申请,所以第二次 for 循环申请 1M 空间就触发了 GC,数据就被丢进老年代,间断 3 次后,GC 堆的空间由 5M 变为了 6M,阐明初始化堆空间不够使,能够主动扩大堆内存。
当然咱们还能够通过-Xmn 设置年老代大小。上面咱们看看年老代中,Eden 和 from/to 区域怎么划分。
下面程序不变,设置 JVM 参数,-XX:+PrintGCDetails -Xmx20m -Xmn10m -XX:SurvivorRatio=2,运行程序,局部后果如下图所示。
- -Xmn10m:设置新生代内存为 10m。
- -XX:SurvivorRatio=2:设置新生代中 eden 和Survivor 比例是 2:1。
咱们设置新生代是 10M,这里显示新生代大小是 7.5M(7680K), 实际上 from/to 是有一块空间是每次 GC 做替换的区域(不便垃圾回收),所以实际上 7680K=5120+2560。5120/2560=2,也就是新生代和 和Survivor 空间比例。
另外还有:-XX:NewRatio:设置老年代和新生代比例,个别是 1 /3)。比方设置 -XX:NewRatio=2 -XX:+PrintGCDetails -Xmx30m
那么老年代空间是 20M,新生代空间是 10M。
总结
最初总结下:
- -XX:+PrintGCDetails:打印 GC 详细信息。
- -Xmx20m:调配最大堆内存空间是 20m。
- -Xmn10m:设置新生代内存为 10m。
- -XX:SurvivorRatio=2:设置新生代中 eden 和Survivor 比例。
- -XX:NewRatio:设置老年代和新生代比例,个别是 1 /3)。
明天学习了 JVM 之 GC 信息参数配置,写的不全同时还有许多须要修改的中央,心愿亲们加以斧正和点评,喜爱的请点赞加关注哦。点关注,不迷路,我是【叫练 】 公众号 ,微信号【jiaolian123abc】 边叫边练。