Groovy Update verursacht eine Menge toter GroovyClassLoader in PermGen

Ich habe ein Java 7-Projekt, das alle n Minuten Skripte von n Prozessen ausführt. Hier ist ein Beispiel für den Code, mit dem die Skripte ausgeführt werden.

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();

Aus irgendeinem Grund gibt es mit Groovy 2.1.7 keinen Speicherverlust in Perm Gen. Beim Upgrade auf Groovy 2.3.8 oder Groovy 2.2.0 wird Perm Gen weiterhin mit toten Groovy-Klassenladern gefüllt.

0x000000071ada2cd0 33 488160 0x000000071b2493c8 tot groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x00000007265883b8 33 488160 0x0000000725837270 tot groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x00000007157b5da0 26 370736 0x000000072326f468 Live-org / Codehaus / groovy / runtime / callsite / CallSiteClassLoader @ 0x00000007c831d388 0x000000071ada1fb0 32 423944 0x000000071af03a98 tot groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x0000000719d605b0 32 456520 0x000000071af04798 tot groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x0000000725b82500 0 0 0x000000072326f468 tot groovy / lang / GroovyClassLoader @ 0x00000007c74c33e8 0x00000007263eef80 34 532448 0x0000000726d5c678 tot groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x000000072687b3c8 33 485288 0x0000000726c36340 dead groovy / lang / GroovyClassLoader $ InnerLoader @ 0x00000007c7b70ef8 0x0000000725d56db0 33 485288 0x000000072607bcc0 ader @ 0x00000007c7b70ef8

Ich warte, bis ein vollständiger GC stattfindet, aber es scheint, dass jede Version nach Groovy 2.2 Perm Gen zum Auffüllen gebracht hat. Ich habe die Versionshinweise zwischen meiner aktuellen Version und der aktualisierten Version überprüft und keine Änderungen festgestellt, die dies auslösen würden.

Ich habe hier nach ähnlichen Problemen gesucht und ein paar Vorschläge ausprobiert, aber kein Glück. Irgendwelche Ideen bezüglich der Ursache?

Aktualisieren
Ich habe GrepCode in GroovyClassLoader von 2.1.7 auf 2.2.0 verbessert und es wurden keine Änderungen vorgenommen. Ich habe auch eine Heap-Dump-Datei erstellt, als die Anwendung ausgeführt wurde, und es gab keine Pfade zu GC-Roots für starke Verweise.

Das Problem scheint hier zu sein:

Class scriptClass = cl.parseClass(scriptSource);
Foo script = scriptClass.newInstance();

Wenn ich das Skript nicht kompiliere, habe ich 0 Groovy ClassLoader in Perm Gen. Wenn ich das Skript kompiliere, aber nicht ausführe, bekomme ich keine Groovy ClassLoader mehr.

Aktualisieren
Funden Sie den Code, der das Leck verursacht.

Foo script = scriptClass.newInstance();

Not sure, wie man dieses regelt, während ich eine neue Instanz verursachen muss, um das Index laufen zu lassen.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage