Gernot Bauer created GROOVY-8035:
------------------------------------

             Summary: Class unloading (PermGen) memory leak with Groovy Shell
                 Key: GROOVY-8035
                 URL: https://issues.apache.org/jira/browse/GROOVY-8035
             Project: Groovy
          Issue Type: Bug
    Affects Versions: 2.4.7
         Environment: Oracle JDK6, Oracle JDK7
            Reporter: Gernot Bauer


The following code causes a memory leak in perm gen reproducibly on Oracle JDK6 
and 7.

{code:java}
import groovy.lang.GroovyShell;

public class Demo {


    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10000000; i++) {
            GroovyShell gs = new GroovyShell();
            Object result = gs.evaluate(" 'Hello, World';");
            assert result.equals("Hello, World");
        }
    }
}
{code}

Tested with the following VM options (with PermGen size 20MB), the execution 
results in java.lang.OutOfMemoryError: PermGen space after a little more than 
2000 iterations.

{noformat}
-verbose:class -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 
-XX:+CMSClassUnloadingEnabled -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses 
-XX:+TraceClassUnloading -XX:MaxPermSize=16M -XX:+UseConcMarkSweepGC 
-XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:-UseParNewGC
{noformat}

As a workaround, calling the following method with script.getClass() from above 
(as described in http://stackoverflow.com/a/41473210/2156613) seems to avoid 
this leak and trigger class unloading correctly:
{code:java}
    public static void clearAllClassInfo(Class<?> type) {
        try {
            Field globalClassValue = 
ClassInfo.class.getDeclaredField("globalClassValue");
            globalClassValue.setAccessible(true);
            GroovyClassValue classValueBean = (GroovyClassValue) 
globalClassValue.get(null);
            classValueBean.remove(type);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
{code}

This should be handled by Groovy itself, or (if this is not possible) there 
should be at least a possibility to trigger this functionality via a Groovy API 
call instead of having to create the above method in all applications using 
Groovy.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to