最近,我们java.lang.OutOfMemoryError: Metaspace在微服务应用程序中遇到了一个有趣的问题。这个微服务应用程序会在最初的几个小时内平稳运行,但稍后会开始抛出java.lang.OutOfMemoryError: Metaspace. 在这篇文章中,让我分享我们为解决此问题所采取的步骤。
JVM 内存有以下区域:
当您遇到 时java.lang.OutOfMemoryError: Metaspace,表明 JVM 内存中的 Metaspace 区域正在饱和。元空间是存储执行应用程序所需的元数据详细信息的区域。简而言之,它包含应用程序的类定义、方法定义和其他元数据。要了解有关在每个 JVM 内存区域中存储的内容的更多信息,您可以参考此视频剪辑:JVM 内存 - 轻松学习。
注意:有 9 种不同类型的java.lang.OutOfMemoryErrors。您可以在“ OutOfMemoryErrors的风味”一文中了解这些内容。java.lang.OutOfMemroyError: Metaspace是其中的一种,但不是常见的类型。
开始调试的最佳位置java.lang.OutOfMemoryError是垃圾收集日志。如果您还没有为您的应用程序启用垃圾收集日志,您可以考虑通过传递此处提到的 JVM 参数来启用它。启用垃圾收集日志不会 给您的应用程序增加明显的开销。因此,建议在所有生产 JVM 实例上启用垃圾收集日志。在此处了解有关如何查看垃圾收集日志的巨大好处的更多信息。
我们将这个陷入困境的微服务应用的垃圾回收日志上传到了GCeasy-GC日志分析工具。这是该工具生成的GC日志分析报告。下面是该工具报告的堆使用情况图。
GCeasy 报告的堆使用情况图
我想强调一下这张图中的一些观察结果:
GCeasy 报告的元空间使用图
您可以注意到 Metaspace 区域的内存消耗呈锯齿状增长和下降,直到上午 12:30。上午 12:30 之后,Metaspace 区域的内存消耗根本没有下降,即使 Full GC 连续运行。它表示垃圾收集事件无法释放元空间。它清楚地表明元空间区域存在内存泄漏 。
现在我们已经确认 Metaspace 区域发生了内存泄漏。因此,下一个合乎逻辑的步骤是检查元空间区域并尝试了解哪些对象占据了该区域。有 5 种不同的方法来研究 Metaspace 区域中的内容。我们选择了堆转储分析方法。
基本上,我们使用 yCrash 工具来捕获堆转储并对其进行分析。该工具立即指出了问题:它报告了一个正在经历的线程OutOfMemoryError。显然,该线程OutOfMemoryError在调用 3 rd方库时遇到了问题。由于一个错误,这个第 3方库正在为每个新请求创建新的类定义。此应用程序在此 3 rd方库的旧版本上运行。但是,此错误已在最新版本的库中修复。将 3rd 方库升级到最新版本后,此问题得到解决。
https://youtu.be/R7I5o1ccRoU
留言与评论(共有 0 条评论) “” |