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

简介: 我的程序跑了60多小时,就是为了让你看一眼JDK的BUG导致的内存泄漏。 (3)

程序运行 19 分 06 秒后,发生 OOM 异常:


那正常的走势图应该是怎么样的呢?


我们在 JDK 1.8.0_121 版本中(已经修复了 remove 方法),用相同的 JVM 参数(-Xmx20m)再跑一下:


首先从上面的日志中可以看出,时间间隔并没有递增,程序运行的非常的快。


然后用 VisualVM 检测内存,同样跑 19 分钟后截图如下:


可以看到堆内存的使用量并没有随着时间的推移而越来越高。但是还是有非常频繁的 GC 操作。


这个不难理解,因为 CLQ 的数据结构用的是链表。而链表又是由不同的 node 节点组成。


由于调用 remove 方法后,node 节点具备被回收的条件,所以频繁的调用 remove 方法对节点进行删除,会触发 JVM 的 min GC。


这种 JDK BUG 导致的内存泄漏其实挺让人崩溃的。首先你第一次感知到它是因为程序发生了 OOM。


也许你会先无脑的加大堆内存空间,恰好你的程序运行了一周之后又要上线了,所以涉及到重启应用。


然后很长一段时间内没有发生 OOM 了。你就想这个问题可能解决了。


但是它还是在继续发生着,很可能由于节假日前后不能上线,比如国庆七天,加上前后几天,大概有半个月的样子应用没有上线,所以没有重启,程序越来越慢,最终导致第二次 OOM 的出现。


这个时候,你觉得可能不是内存溢出这么简单了。


会不会是内存泄漏了?


然后你再次重启。这次重启之后,你开始时不时的 Dump 一下内存,拿出来分析分析。

突然发现,这个 node 怎么这么多呢?


最终,找到这个问题的原因。


原来是 JDK 的 BUG。


你就会发出和 Greg 一样的感叹:卧槽,震惊,这么牛皮!?


我这个运行了 60 多小时的程序到现在堆内存使用了 233m,但是我整个堆的大小是接近 2G。


通过 jmc 同时展示堆的整体大小和已经使用的堆大小你可以发现,距离内存泄漏可以说是道阻且长了:


我粗略的算了一下,这个程序大概还得运行 475 个小时左右,也就是 19 天之后才会出现由于内存泄漏,导致的 OOM。


我会尽量跑下去,但是听到我电脑嗡嗡嗡的风扇声,我不知道它还能不能顶得住。


如果它顶住了,我在后面的文章里面通知大家。


好了,图形化工具这一小节就到这里了。


我们只是展示了它们非常小的一个功能,合理的使用它们常常能达到事半功倍的作用。


如果你不太了解它们的功能,建议你看看《深入理解JVM虚拟机(第3版)》,里面有一章节专门讲这几个工具的。



最后说一句(求关注)


这是我昨天晚上写文章的时候拍的 ,女朋友说一眼望去感觉我是一个盯盘的人,在看股票走势图,这只股票太牛逼了。


要是股市的总体走势也像内存泄露那么单纯而直接就好了。


只要在 OOM 之前落袋为安就行。可惜有的人就是在 OOM 的前一刻满仓杀入,真是个悲伤的故事。


文中提到的两本书,都是非常优秀的值得学习的书籍。作为一个 Java 程序员,如果你还没有拥有这两本书,我强烈建议你买来看看。


买不了吃亏,买不了上当,只会觉得相见恨晚。你会发现原来这么多 JVM、多线程相关的面试题都是出自这两本书:


才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你留言指出来,我对其加以修改。


感谢您的阅读,我坚持原创,十分欢迎并感谢您的关注。


我是 why,一个被代码耽误的文学创作者,不是大佬,但是喜欢分享,是一个又暖又有料的四川好男人。

目录
相关文章
|
3月前
|
存储 程序员 C语言
【动态内存管理助力程序优化与性能飞升】(下)
【动态内存管理助力程序优化与性能飞升】
|
3月前
|
C语言
【动态内存管理助力程序优化与性能飞升】(中)
【动态内存管理助力程序优化与性能飞升】
|
18天前
|
存储 编译器 C语言
深入探索C语言动态内存分配:释放你的程序潜力
深入探索C语言动态内存分配:释放你的程序潜力
28 0
|
3月前
|
存储 缓存 Java
Java性能优化: 如何减少Java程序的内存占用?
Java性能优化: 如何减少Java程序的内存占用?
244 2
|
4月前
|
Java Maven
[Java ] jdk升级 bug java: -source 8 中不支持 instanceof 中的模式匹配 (请使用 -source 16 或更高版本以启用 instanceof 中的模式匹配)
[Java ] jdk升级 bug java: -source 8 中不支持 instanceof 中的模式匹配 (请使用 -source 16 或更高版本以启用 instanceof 中的模式匹配)
137 0
|
1月前
|
缓存 算法 编译器
C/C++编译器内存优化技术:内存优化关注程序对内存的访问和使用,以提高内存访问速度和减少内存占用。
C/C++编译器内存优化技术:内存优化关注程序对内存的访问和使用,以提高内存访问速度和减少内存占用。
40 0
|
5月前
|
存储
【OS Pintos】用户程序是如何工作的 | Pintos 运行原理 | 虚拟内存 | 页函数 | 系统调用
【OS Pintos】用户程序是如何工作的 | Pintos 运行原理 | 虚拟内存 | 页函数 | 系统调用
164 0
|
2月前
|
监控 Java 编译器
优化Go语言程序中的内存使用与垃圾回收性能
【2月更文挑战第5天】本文旨在探讨如何优化Go语言程序中的内存使用和垃圾回收性能。我们将深入了解内存分配策略、垃圾回收机制,并提供一系列实用的优化技巧和建议,帮助开发者更有效地管理内存,减少垃圾回收的开销,从而提升Go程序的性能。
|
2月前
|
运维 监控 算法
JDK 21中的分代ZGC:内存管理的革命性进步
本文深入探讨了JDK 21中引入的分代ZGC(Z Garbage Collector)的工作原理、特性及其对现代应用程序性能的影响。分代ZGC是一种基于分代收集的垃圾回收器,通过优化内存分配和回收过程,实现了更高的吞吐量和更低的延迟。本文将分析分代ZGC的设计哲学、技术细节以及在实际应用中的优势,并展示如何通过配置和优化分代ZGC来提升Java应用程序的性能。
|
3月前
|
存储 程序员 编译器
C/C++程序内存区域划分以及各区域的介绍
C/C++程序内存区域划分以及各区域的介绍