GC频繁Finalizer的锅?记一次频繁GC问题的排查

1 篇文章 0 订阅

前言

最近有一个服务gc频繁,这个服务是调用多个三方平台,返回的数据没有大对象,再将数据返回,基本没有多余逻辑。

分析

拿到dump日志之后,使用mat工具分析一波,发现都是 java.lang.ref.Finalizer 对象,这个对象没怎么见过,搜索资料之后,才知道这是实现了finalize() 方法的对象会被标记成这个类,然后有 finalizerThread 单独处理他们。

搜索的时候搜到了一篇好文:《线上环境频繁GC问题排查,Finalizer对象该背这个锅吗?》,和我们项目场景很像,使用文中的mat方法观察后,也是有很多 HttpsURLConnectionImpl 、 ZipFile$ZipFileInflaterInputStream 对象等。
那么原因初步找到,引用文中的话,就是每次请求都会 new HttpURLConnection 对象,请求完毕 该对象及其关联的对象并没有立即释放内存而是进入了ReferenceQueue队列等待Finalizer 的守护线程来回收。如果主线程的请求比较频繁,就会产生大量的Finalizer对象放入到Queue中。而守护线程的优先级是比较低导致回收Finalizer对象的速度远低于主线程产生的速度,这样就导致了eden区内存迅速的被Finalizer对象占满。
我们请求第三方服务用的是 hutool 的 HttpUtil,在execute() 方法中,会每次创建连接:

/**
 * 初始化网络连接
 */
private void initConnecton() {
	this.httpConnection = HttpConnection.create(URLUtil.toUrlForHttp(this.url, this.urlHandler), this.proxy)//
			.setMethod(this.method)//
			.setHttpsInfo(this.hostnameVerifier, this.ssf)//
			.setConnectTimeout(this.connectionTimeout)//
			.setReadTimeout(this.readTimeout)//
			// 自定义Cookie
			.setCookie(this.cookie)
			// 定义转发
			.setInstanceFollowRedirects(this.maxRedirectCount > 0 ? true : false)
			// 覆盖默认Header
			.header(this.headers, true);

	// 是否禁用缓存
	if (this.isDisableCache) {
		this.httpConnection.disableCache();
	}
}
// HttpConnection.create 方法如下:
/**
 * 创建HttpConnection
 * 
 * @param url URL
 * @param proxy 代理,无代理传{@code null}
 * @return HttpConnection
 */
public static HttpConnection create(URL url, Proxy proxy) {
	return new HttpConnection(url, proxy);
}

验证

首先不改代码,进行压测:
1.编写一个接口,模拟第三方的接口,sleep 300ms返回
2.服务启动时,JVM启动参数设置最大内存:-Xmx512m
3.使用JMeter设置100线程,压测时间设置为永远
4.等待压测10分钟,使用jps和jmap,将dump日志输出出来
5.接着修改代码,将 hutool 的 HttpUtil 换成 OKHttp ,并且设置连接池为5
6.对修改的服务进行压测,输出10分钟的dump文件

压测结果对比

修改代码前,Finalizer对象占用了84,762,136 (51.50%) bytes

修改代码后,Finalizer对象占用了6,331,344 (7.38%) bytes

效果比较明显,不过连接池的数量,还是需要根据实际场景来设置。

附录

这里发几个还不错的链接:

  1. MAT(Memory Analyzer Tool)下载:
    https://www.eclipse.org/mat/

  2. MAT(Memory Analyzer Tool)工具使用超详细版
    https://blog.csdn.net/lyd135364/article/details/121449969

  3. 线上环境频繁GC问题排查,Finalizer对象该背这个锅吗?
    https://blog.csdn.net/libankling2008/article/details/116789217

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值