[
https://issues.apache.org/jira/browse/GROOVY-8035?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Gernot Bauer updated GROOVY-8035:
---------------------------------
Description:
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();
Script script = gs.parse(" 'Hello, World';");
Object result = script.run();
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.
was:
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.
> 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();
> Script script = gs.parse(" 'Hello, World';");
> Object result = script.run();
> 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)