其他分享
首页 > 其他分享> > 054、JVM实战总结: 案例实战:每日百亿数据量的实时分析引擎,如何定位和解决频繁Full GC问题?

054、JVM实战总结: 案例实战:每日百亿数据量的实时分析引擎,如何定位和解决频繁Full GC问题?

作者:互联网

之前有位同学面试时的一个面试题:如何配置能让JVM不进行FullGC?大家仔细看完这篇文章应该就有答案了

1-7、回顾内容参照40讲 点击链接

 

8JVM参数与程序

参数配置:
-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元

标签:实战,触发,Full,YGC,Eden,XX,30M,数据量,byte
来源: https://blog.csdn.net/dingshuo168/article/details/100049340