内存调优实例:JVM堆大小

1、创建一个Spring Boot实例

@RestController
public class GcTestController {
    private Queue queue = new ConcurrentLinkedQueue<>();
    @RequestMapping("/greeting")
    public Greeting hello() {
        Greeting greeting = new Greeting("Hello world!");
        if(queue.size()>200000){
            queue.clear();
        }else{
            queue.add(greeting);
        }
        return greeting;
    }

}


class Greeting{
    private String message;

    public Greeting(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

备注:这样一个代码竟然在controller里开辟了一个队列用来存放对象,这个队列在达到20万的容量后才会清空。这些对象会驻留在老年代,用来模拟老年代的gc情况。

2、命令行启动程序

java -Xmx32m -Xss256k -verbose:gc -Xloggc:"mylog.txt" -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar .\demo-0.0.1-SNAPSHOT.jar

备注:堆设计为这么小,是为了能出现Full GC。打开verbose:gc是为了输出日志,待日后将日志文件放入GCViewer,可视化查看GC情况。

3、使用JMeter这个有趣的压测工具,进行压测。

内存调优实例:JVM堆大小_第1张图片

内存调优实例:JVM堆大小_第2张图片

备注:开启50个线程,每个线程发起10000次请求,每次请求路径为/greeting

4、大概经过12分钟左右你的服务就歇菜了。然后,用GCViewer查看刚才输出的日志文件mylog.txt

内存调优实例:JVM堆大小_第3张图片

备注:蓝色线条是已经使用的堆空间量,绿色线条表示年轻代的gc活跃情况,黑线是老年代的full gc,当程序濒临奔溃时黑线出现频率非常之高,已成黑柱。

内存调优实例:JVM堆大小_第4张图片

备注:

1、full gc不光是由于老年代空间不够了(Allocation Failure)进行gc;还有jvm的自适应调整机制导致的full gc,Ergonomics full gc,在JVM中的垃圾收集器中的Ergonomics就是负责自动的调解gc暂停时间和吞吐量之间的平衡,然后你的虚拟机性能更好的一种做法,提前预测到可能的问题,提前发生一次full gc。

2、本文controller中的队列,在单例模式下,每个请求过来都存一个对象在队列中,达到20万长度才清除,导致老年代空间不足,频频发生full gc。最终导致java.lang.OutOfMemoryError: GC overhead limit exceeded,出现这种 OutOfMemoryError 的原因是,垃圾收集器一直在运行,但是 GC 效率很低,比如 Java 进程花费超过 98%的 CPU 时间来进行一次 GC,但是回收的内存少于 2%的 JVM 堆,并且连续 5 次 GC 都是这种情况,就会抛出 OutOfMemoryError。

3、主要是用于测试,所以开头开辟的堆空间太少,可以把堆空间提高到1024m试试。

 

 

你可能感兴趣的:(调优)