groovy脚本导致FullGC问题排查

背景: 
应用中内嵌了groovy引擎,会动态执行传入的表达式并返回执行结果 
线上问题:

  • 发现机器的fullGC从某个时候开始暴涨,并且一直持续;
  • 登到机器上,用jstat -gcutil 命令观察,发现perm区一直是100%,fullGC无法回收;
  • 将这台机器的内存dump出来进行分析;
  • 在类视图中,发现大量的groovy.lang.GroovyClassLoader$InnerLoader;
  • 在类加载器视图里面也看到大量的groovy的InnerLoader;
  • 基本上可以定位问题在groovy脚本的加载处;

    初步的问题分析:

groovy每执行一次脚本,都会生成一个脚本的class对象,并new一个InnerLoader去加载这个对象,而InnerLoader和脚本对象都无法在fullGC的时候被回收,因此运行一段时间后将PERM占满,一直触发fullGC。

因此,跟了一下groovy的编译脚本的源码

脚本编译的入口是GroovyShell的parse方法:

public Script parse(GroovyCodeSource codeSource)    throws CompilationFailedException
 {
 return InvokerHelper.createScript(parseClass(codeSource), this.context);
}

所有的脚本都是由GroovyClassLoader加载的,每次加载脚本都会生成一个新的InnerLoader去加载脚本,但InnerLoader只是继承GroovyClassLoader,加载脚本的时候,也是交给GroovyClassLoader去加载:

创建新的innerLoader:

InnerLoader loader = (InnerLoader)AccessController.doPrivileged(new PrivilegedAction() {
public GroovyClassLoader.InnerLoader run() {
return new GroovyClassLoader.InnerLoader(GroovyClassLoader.this);
     }
   });

innerLoader继承GroovyClassLoader:

 public static class InnerLoader extends GroovyClassLoader {
    private final GroovyClassLoader delegate;
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值