【发布时间】:2017-02-24 19:38:19
【问题描述】:
在我们的 Wildfly 10 应用服务器上,我们使用 groovy 处理 jasperreports 和其他类似系统。 一段时间后,jvm (java 8) 出现“内存不足:元空间”错误。 同样的问题发生在一些带有 permgen (java 6) 的旧 jboss 4 服务器上。 我们将 jasperreports 从 3.7.2 升级到 6.3.1,问题仍然存在。 permgen/metaspace 的大小足够大(最大 512 MB)。
我们其他不使用 jasperreports 和 groovy 的应用程序没有这个问题。
经过一些研究,我意识到这可能是类加载器中的内存泄漏 (stackoverflow question)。似乎 gc 不会卸载从 groovy 生成的类。
在jaspersoft documentation 他们写道,您应该将-XX:+UseConcMarkSweepGC 和-XX:+CMSClassUnloadingEnabled 设置为VM 参数以启用类卸载。
所以我们改变了它,但问题仍然存在。 Java 8 是否仍然支持这些参数?如果没有,还有其他解决方案。 目前我们必须每晚重新启动服务器以避免此问题。
【问题讨论】:
-
您是否尝试过为应用程序获取堆转储?它可能会提供一些关于正在分配的内容的见解。如果您寻找一个大集合生成的类,您也许能够找到它们被分配的位置。
-
您很可能确实存在类加载器泄漏。如果您有一个很好的测试 ENV,您可以在其中重现该问题,请尝试在盒子上运行 jmap -clstats
。这将导致应用程序挂起并需要几分钟才能运行(在我的应用程序中大约需要 10 分钟),但它会为您提供类加载器及其状态的完整列表。您很可能会看到大量的死载类型:“sun/reflect/DelegatingClassLoader”和“org/codehaus/groovy/runtime/callsite/CallSiteClassLoader” -
我会查看通过堆转储保留的类。这是内存泄漏的最可能原因。 0.5 GB 应该足够大,但不是很大。如果你把它设为 4 GB,你能在两次重启之间运行一周吗?
-
取决于使用情况。大多数情况下,我们可以运行 2 天而无需重新启动,因此 4GB 应该可以运行一周。下周我会将元空间更改为最大 4GB,并在 2 或 3 天后进行堆转储。感谢到目前为止的帮助,我会在分析堆转储后发布我的结果。
-
正如 Durandal 提到的,堆转储中有很多“sun/reflect/DelegatingClassLoader”和“org/codehaus/groovy/runtime/callsite/CallSiteClassLoader”条目。 groovy 似乎有一些内存泄漏问题。我们将脚本 enginge 从 groovy 更改为 java 用于 jasper 报告和 javascript 用于我们的其他系统。这解决了问题。感谢您的帮助。
标签: java groovy jvm jasper-reports wildfly