简单的 Grails 2.5.1 应用程序使用 Groovy 2.4.4 泄漏类加载器
Simple Grails 2.5.1 application leaks classloaders with Groovy 2.4.4
我在 Tomcat 8 中热重新部署一个简单的 Grails 应用程序时遇到问题。
我的设置如下:
- Grails 2.5.1 全新应用程序,刚刚使用
create-app
创建
- Tomcat 8.0.28(64 位 Linux 二进制版本)
- Java 1.8.0_65-b17 HotSpot 服务器虚拟机
Tomcat也是一个全新的安装,只修改了两个东西(因为我想在生产中使用它们):
server.xml
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" undeployOldVersions="true">
context.xml
<Context antiResourceLocking="true">
我已经重新启动了 Tomcat 服务器。根据 JVisualVM,它加载了 2398 类。复制 grails prod war
生成的 war 文件并等待部署完成后,它加载了 10 022 类。再次复制 war 并触发重新部署后,它有 16 300 类.
我在第一次部署和第二次部署后进行了堆转储,并使用 eclipse MAT 分析类加载器,我可以看到有一个额外的 org.apache.catalina.loader.WebappClassLoader
加载了 6 138 类(所以总共有两个)。
堆 space 保持相当稳定,只有 MetaSpace 使用率显着增加(与 类 的数量大致相同)。
更新
使用 MAT 进行更深入的挖掘,我注意到总是有 9 个实例使类加载器保持活动状态。它们是 org.codehaus.groovy.reflection.ClassInfo
的实例(每个原始 java 类型包装器和 Void
一个)。这些 ClassInfos 仅由扩展 WeakReference
的 java.lang.ClassValue$Entry
引用,所以我真的很困惑这些实例是如何没有被垃圾收集的。
有没有人遇到过类似的问题?什么会导致此加载程序挂起?
此问题与 https://issues.apache.org/jira/browse/GROOVY-7591
有关
我不完全理解这个问题,但我会尽量描述一下:
使用 ClassValue
(由于 JDK 错误)可防止对象被垃圾收集。 Groovy 2.4.5 中的提交暂时禁用了 ClassValue
的使用,同时 JDK 错误得到修复。
Grails 2.5.1 默认使用 groovy 2.4.4,为了解决这个问题,我在 BuildConfig.groovy
中替换了它,并重新构建了应用程序。
build 'org.codehaus.groovy:groovy-all:2.4.5'
compile 'org.codehaus.groovy:groovy-all:2.4.5'
我在 Tomcat 8 中热重新部署一个简单的 Grails 应用程序时遇到问题。
我的设置如下:
- Grails 2.5.1 全新应用程序,刚刚使用
create-app
创建
- Tomcat 8.0.28(64 位 Linux 二进制版本)
- Java 1.8.0_65-b17 HotSpot 服务器虚拟机
Tomcat也是一个全新的安装,只修改了两个东西(因为我想在生产中使用它们):
server.xml
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" undeployOldVersions="true">
context.xml
<Context antiResourceLocking="true">
我已经重新启动了 Tomcat 服务器。根据 JVisualVM,它加载了 2398 类。复制 grails prod war
生成的 war 文件并等待部署完成后,它加载了 10 022 类。再次复制 war 并触发重新部署后,它有 16 300 类.
我在第一次部署和第二次部署后进行了堆转储,并使用 eclipse MAT 分析类加载器,我可以看到有一个额外的 org.apache.catalina.loader.WebappClassLoader
加载了 6 138 类(所以总共有两个)。
堆 space 保持相当稳定,只有 MetaSpace 使用率显着增加(与 类 的数量大致相同)。
更新
使用 MAT 进行更深入的挖掘,我注意到总是有 9 个实例使类加载器保持活动状态。它们是 org.codehaus.groovy.reflection.ClassInfo
的实例(每个原始 java 类型包装器和 Void
一个)。这些 ClassInfos 仅由扩展 WeakReference
的 java.lang.ClassValue$Entry
引用,所以我真的很困惑这些实例是如何没有被垃圾收集的。
有没有人遇到过类似的问题?什么会导致此加载程序挂起?
此问题与 https://issues.apache.org/jira/browse/GROOVY-7591
有关我不完全理解这个问题,但我会尽量描述一下:
使用 ClassValue
(由于 JDK 错误)可防止对象被垃圾收集。 Groovy 2.4.5 中的提交暂时禁用了 ClassValue
的使用,同时 JDK 错误得到修复。
Grails 2.5.1 默认使用 groovy 2.4.4,为了解决这个问题,我在 BuildConfig.groovy
中替换了它,并重新构建了应用程序。
build 'org.codehaus.groovy:groovy-all:2.4.5'
compile 'org.codehaus.groovy:groovy-all:2.4.5'