线上环境 使用Groovy脚本为业务提供自定义配置 结果 没几天就fullGC 并且持续很长时间,才降下来,
groovy 常见的三种引入方式都会有对应的问题,:
核心的问题是Groovy会缓存掉曾经执行的代码片段成为META-class ,如果每次执行的代码都不一样。那么缓存的类会越来越多。
相应的解决办法:
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.7</version>
</dependency>
//清除groovy 里面的缓存, 防止fullGC,也可以定时来做
GroovyClassLoader groovyClassLoader = engine.getClassLoader();
Class[] classes = engine.getClassLoader().getLoadedClasses();
for (Class clazz : classes) {
GroovySystem.getMetaClassRegistry().removeMetaClass(clazz);
groovyClassLoader.clearCache();
try {
Field globalClassValue = ClassInfo.class.getDeclaredField("globalClassValue");
globalClassValue.setAccessible(true);
GroovyClassValue classValueBean = (GroovyClassValue) globalClassValue.get(null);
classValueBean.remove(clazz);
} catch (Throwable e) {
}
}
groovyClassLoader.clearCache();
ClassInfo.clearModifiedExpandos();
/**
* Using java beans (e.g. Groovy does it) results in all referenced class infos being cached in ThreadGroupContext. A valid fix
* would be to hold BeanInfo objects on soft references, but that should be done in JDK. So let's clear this cache manually for now,
* in clients that are known to create bean infos.
*/
Introspector.flushCaches();