我的程序跑了60多小时,就是为了让你看一眼JDK的BUG导致的内存泄漏

本文讲述了由于JDK中ConcurrentLinkedQueue的内存泄漏问题,导致程序长时间运行后出现内存占用不断增长的现象。通过分析jetty项目中的问题,展示了错误使用ConcurrentLinkedQueue如何引发内存泄漏,以及修复这个问题的方法。同时,文章介绍了如何使用jconsole、VisualVM和jmc等工具监控和排查内存泄漏问题。
摘要由CSDN通过智能技术生成

从一个BUG说起

前段时间翻到了一个 JDK 有点意思的 BUG,带大家一起瞅瞅。

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8137185

memory leak,内存泄漏。

是谁导致的内存泄漏呢?

ConcurrentLinkedQueue,这个队列。

这个 BUG 里面说,在 jetty 项目里面也爆出了这个 BUG:

我看了一下,觉得 jetty 的这个写得挺有意思的。

我按照 jetty 的这个讲吧,反正都是同一个 JDK BUG 导致的。地址如下:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=477817

我用我八级半的蹩脚英语给大家翻译一下这个叫做 max 的同学说了些什么。

他说:在 Java 项目里面,错误地使用 ConcurrentLinkedQueue(文章后面用缩写 CLQ 代替)会导致内存泄漏的问题。

在 jetty 的 QueuedThreadPool 这个线程池里面,使用了 CLQ 这个队列,它会导致内存缓慢增长,最终引发内存泄漏。

虽然 QueuedThreadPool 仅仅使用了这个队列的 add 方法和 remove 方法。但不幸的是,remove 方法不会把队列的大小变小,只会使队列里面被删除的 node 为空。因此,该列表将增长到无穷大。

然后他给了一个附件,附件里面是一段程序,可以演示这个问题。

我们先不看他的程序,后面我们统一演示这个问题。

先给大家看一下 jetty 的 QueuedThreadPool 线程池。

看哪个版本的 jetty 呢?

可以看到这个 BUG 是在 2015 年 9 月 18 日被爆出来的。所以,我们找一个这个日期之前的版本就行。

于是我找了一个 2015 年 9 月 3 日发布的 maven 版本:

在这个版本里面的 QueuedThreadPool 是这样的:

可以看到,它确实使用了 CLQ 队列。

而从这个对象所有被调用的地方来看,jetty 只使用了这个队列的 size、add、remove(obj) 方法:

和前面 max 同学描述的一致。

然后这个 max 同学给了几张图片,来佐证他的论点:

主要关注我框起来的地方,就是说他展示了一张图片。可以从这图片中看出内存泄漏的问题,而这个图片的来源是他们真实的项目。

这个项目已经运行了大约两天,每五分钟就会有一个 web 请求过来。

下面是他给出的图片:

从他的这个图片中,我就只看出了 CLQ 的 node 很多。

但是他说了,他这个项目请求量并不大,用的 jetty 框架也不应该创建这么多的 node 出来。

好了,我们前面分析了 max 同学说的这个问题,接下来就是大佬出场,来解惑了:

我们先不看回答,先看看回答问题的人是谁。

Greg Wilkins,何许人也?

我找到了他的领英地址:

https://www.linkedin.com/in/gregwilkins/?originalSubdomain=au

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值