Groovy更新导致PermGen中大量的GroovyClassLoaders死机

Col*_*nMc 2 java groovy permgen

我有一个Java 7项目,它每n分钟由n个进程运行一次脚本。这是运行脚本的代码示例。

ScheduledFuture scheduledFuture = scheduledService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try (GroovyClassLoader cl = new GroovyClassLoader()) {
                    // Load up reusable script modules in the class loader
                    Class scriptClass = cl.parseClass(scriptSource);
                    Foo script = optimizationClass.newInstance();

                    // Tell Groovy that we don't need class meta info
                    GroovySystem.getMetaClassRegistry().removeMetaClass(scriptClass);
                    script.run();
                    cl.clearCache();
                } catch (IOException e) {
                    LOGGER.error("Failed to cleanup Groovy class loader, this will cause a memory leak", e);
                }
            }
        }, 0, scheduledRun, TimeUnit.SECONDS);

        scheduledFuture.get();
Run Code Online (Sandbox Code Playgroud)

由于某些原因,Groovy 2.1.7在Perm Gen中没有内存泄漏。当升级到Groovy 2.3.8或Groovy 2.2.0时,Perm Gen总是充满死掉的Groovy类加载器。

0x000000071ada2cd0 33 488160 0x000000071b2493c8死常规/郎/ GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x00000007265883b8 33 488160 0x0000000725837270死常规/郎/ GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x00000007157b5da0 26 370736 0x000000072326f468活组织/ Codehaus的/常规/运行/调用点/ CallSiteClassLoader @ 0x00000007c831d388 0x000000071ada1fb0 32 423944 0x000000071af03a98死槽groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x0000000719d605b0 32 456520 0x000000071af04798死槽groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8ovclange0700000070000007204e0700000076003e00000007 / 0000000000000000/0000003226groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x000000072687b3c8 33 485288 0x0000000726c36340 dead groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8xovererner @ nergroyergro @ 7gro70ery @ gro7ery7gro70y / 7700607y6070y7y0b0b0f加载

我等到完全GC出现,但是Groovy 2.2之后的任何版本似乎都导致Perm Gen填满。我检查了我所使用的版本与最新版本之间的发行说明,但没有发现任何会触发此更改的更改。

我在这里检查了类似的问题,并尝试了一些建议,但没有运气。关于原因有什么想法吗?

更新:
我在GroovyClassLoader上的GrepCode上做了一个从2.1.7到2.2.0的比较,并且没有任何变化。当应用程序运行时,我还提取了一个堆转储文件,并且没有指向GC根的任何路径来获得强引用。

问题似乎在这里:

Class scriptClass = cl.parseClass(scriptSource);
Foo script = scriptClass.newInstance();
Run Code Online (Sandbox Code Playgroud)

当我不编译脚本时,在Perm Gen中得到0个Groovy ClassLoaders。当我编译脚本但不运行它时,我就死掉了Groovy ClassLoaders。

更新:
找到了导致泄漏的代码。

Foo script = scriptClass.newInstance();
Run Code Online (Sandbox Code Playgroud)

不确定如何解决此问题,因为我需要创建一个新实例才能运行脚本。

小智 5

使用groovy脚本进行编译和运行时,我遇到了同样的问题。我终于可以通过以下方式解决:1.如果您使用7以下的Java版本,则可以在编译后使用下面的代码来清理您的类

 public static void clearAllClassInfo(Class<?> type) throws Exception {
    Field globalClassValue = ClassInfo.class.getDeclaredField("globalClassValue");
    globalClassValue.setAccessible(true);
    GroovyClassValue classValueBean = (GroovyClassValue) globalClassValue.get(null);
    classValueBean.remove(type);
}
Run Code Online (Sandbox Code Playgroud)

2.否则您很幸运,因为您只需要在SystemProperties中添加属性

-Dgroovy.use.classvalue=true
Run Code Online (Sandbox Code Playgroud)