0
点赞
收藏
分享

微信扫一扫

JVM GC原理及调优的基本思路

[](()CMS收集器


最重要的是合理地设置年轻代和年老代大小。

  • 年轻代太小,会导致频繁Minor GC,并且很有可能存活期短的对象也不能被回收,GC的效率就不高

  • 年老代太小,容纳不下从年轻代过来的新对象,会频繁触发单线程Full GC,导致较长时间的GC暂停,影响Web应用的响应时间。

[](()G1收集器


不推荐直接设置年轻代大小,和CMS不不同,因为G1会根据算法动态决定年轻代和年老代大小。

因此对于G1,最关心Java堆总大小(-Xmx)。

-XX:MaxGCPauseMillis = n

限制最大GC暂停时间,以尽量不影响请求的响应时间。G1将根据先前收集信息及检测到的垃圾量,估计它可以立即收集的最大区域数量,从而尽量保证GC时间不会超出这个限制。因此G1更“智能”,使用更简单。

[](()内存调优实战

=====================================================================

下面我通过一个例子实战一下Java堆设置得过小,导致频繁的GC,我们将通过GC日志分析工具来观察GC活动并定位问题。

1.首先我们建立一个Spring Boot程序,作为我们的调优对象

@RestController

public class GcTestController {

private Queue objCache = new ConcurrentLinkedDeque<>();

@RequestMapping(“/greeting”)

public Greeting greeting() {

Greeting greeting = new Greeting(“Hello World!”);

if (objCache.size() >= 200000) {

objCache.clear();

} else {

objCache.add(greeting);

}

return greeting;

}

}

@Data

@AllArgsConstructor

class Greeting {

private String message;

}

就是创建了一个对象池,当对象池中的对象数到达200000时才清空一次,用来模拟年老代对象。

命令启动测试程序:

java -Xmx32m -Xss256k -verbosegc -Xlog:gc*,gc+ref=debug,gc+heap=debug,gc+age=trace:file=gc-%p-%t.log:tags,uptime,time,level:filecount=2,filesize=100m -jar target/demo-0.0.1-SNAPSHOT.jar

我给程序设置的堆的大小为32MB,目的是能让我们看到Full GC。除此之外,我还打开了verbosegc日志,请注意这里我使用的版本是Java 12,默认的垃圾收集器是G1。

  • 使用JMeter压测工具向程序发送测试请求,访问的路径是/greeting。

  • 使用GCViewer工具打开GC日志

上部的蓝线表示已使用堆大小,周期上下震荡,这是对象池要扩展到200000才会清空。

绿线表示新生代GC活动,当堆使用率上去了,会触发频繁GC活动。

竖线表示Full GC,伴随着Full GC,蓝线会下降,这说明Full GC收集了老年代中的对象。

综上,Java堆大小不够:

  • GC活动频繁

年轻代GC(绿色线)和年老代GC(黑色线)都比较密集。这说明内存空间不够,也就是Java堆的大小不够。

  • Java的堆中对象在GC之后能够被回收

说明不是内存泄漏。

GCViewer还发现累计GC暂停时间有55.57秒:

![](https://img-blog.csdnimg.cn/d2f31d210ee84eb 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 3a77c59e668581cca.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNTg5NTEw,size_16,color_FFFFFF,t_70)

因此我们的解决方案是调大Java堆的大小,像下面这样:

java -Xmx2048m -Xss256k -verbosegc -Xlog:gc*,gc+ref=debug,gc+heap=debug,gc+age=trace:file=gc-%p-%t.log:tags,uptime,time,level:filecount=2,filesize=100m -jar target/demo-0.0.1-SNAPSHOT.jar

生成的新的GC log分析图如下:

你可以看到,没有发生Full GC,并且年轻代GC也没有那么频繁了,并且累计GC暂停时间只有3.05秒。

[](()总结

=================================================================

举报

相关推荐

0 条评论