之前有位同学面试时的一个面试题:如何配置能让JVM不进行FullGC?大家仔细看完这篇文章应该就有答案了
1-7、回顾内容参照40讲 点击链接
8、JVM参数与程序
参数配置:
-XX:NewSize=100M
-XX:MaxNewSize=100M
-XX:InitialHeapSize=200M
-XX:MaxHeapSize=200M
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=15
-XX:PretenureSizeThreshold=20M
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:d:/gc.log
程序:
public class _54_RealTimeEngine {
static final int M = 1024 * 1024;
static final int K = 1024;
public static void main(String[] args) throws InterruptedException {
Thread.sleep(20_000);
while(true){
loadData();
}
}
private static void loadData() throws InterruptedException {
byte[] data = null;
for(int i=0;i<4;i++){
data = new byte[10*M];
}
data = null;
byte[] data1 = new byte[10*M];
byte[] data2 = new byte[10*M];//触发第一次OLDGC
byte[] data3 = new byte[10*M];
data3 = new byte[10*M];//触发第一次YGC
Thread.sleep(1_000);
}
private static void allocate(int size) {
byte[] bytes = new byte[size];
}
}
程序说明:
每秒有80M的对象要分配到堆中,其中30M在1秒内是存活的。
事实上垃圾收集时的存活对象要看是在哪条语句触发了GC,比如在byte[] data1 = new byte[10*M];语句触发GC ,那么存活对象是0
10、基于jstat分析程序运行的状态
??问题
1、红色1标注的区域,为什么每次都增加10M,而不是每次存活的30M?
答:执行到data3 = new byte[10*M];时发现Eden不够放,触发YoungGC,30M存活复制到S区,发现放不下,直接放入老年代,YGC后Eden放入10M。
2、红色2、3标注的区域,为什么第一次OU增加了30M ,后面增加的是10M 或 20M?
答:比如第二次YGC时OU增加了20M,是因为Eden区本身已经有10M,这时是执行到byte[] data3 = new byte[10*M];触发YGC,也就是说提前了一条语句触发,此时存活20M,这20M晋升,然后放入byte[] data3 = new byte[10*M]; data3 = new byte[10*M];生成的对象
3、红色3标注的区域,为什么到了60多M就会变成30M,而不是OU回收完的0M?
答:此时Eden区已存在30M多点,Eden区不够放,触发了YGC,结果发现老年代也不够放,触发OldGC,回收完是0M,然后放入存活30M
4、红色4标注的区域,为什么YGC从7直接变成了9?
答:eden放不下(触发了YGC -1),且S区放不下,直接放老年代(此时没有对Eden区回收),发现老年代也放不下了,触发OldGC,,回收完是0M,然后放入存活30M。再然后放入触发YGC的10M,发现Eden放不下,再次触发了YGC -2
5、红色5标注的区域,为什么会连续3秒FullGC
答:触发FullGC原因就是老年代空间不够放晋升对象了。第3次OldGC 完成后Eden和Old区使用空间很多:,接着存放存活对象,触发了第4次OldGC,完成后回到程序初始运行状态,此时要晋升的对象有50M多点,又触发了OldGC
11、对JVM性能进行优化
分析这个程序,方法结束后所有的对象都是垃圾对象,也就是说一秒内分配的对象只要S区可以放下,那么下一秒就可以被回收了。此时需要增加S区的大小
参数配置:
-XX:NewSize=200M
-XX:MaxNewSize=200M
-XX:InitialHeapSize=300M
-XX:MaxHeapSize=300M
-XX:SurvivorRatio=2
-XX:MaxTenuringThreshold=15
-XX:PretenureSizeThreshold=20M
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:d:/gc.log
Eden 100M,From To 50M 这样就避免了FULLGC了,但YGC频繁没发避免的,因为每秒耗用的内存太多80M,但没关系,可以看看下图,一次YGC平均耗费4.5ms
本文是《从 0 开始带你成为JVM实战高手》内容总结,版权问题,特此声明。详细内容:
如果购买,成功后加QQ群找群主返现10元