You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Jex Jexler (JIRA)" <ji...@apache.org> on 2016/05/14 18:00:15 UTC
[jira] [Issue Comment Deleted] (GROOVY-7591) Use of ClassValue
causes major memory leak
[ https://issues.apache.org/jira/browse/GROOVY-7591?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Jex Jexler updated GROOVY-7591:
-------------------------------
Comment: was deleted
(was: To me the ideal solution would be to drop the "groovy.use.classvalue" system property in Groovy 2.4.7, to always use ClassValue (with Java 7 and later), but to give the Java VM a ClassValue that it can garbage collect already without a JVM fix.
Why drop the system property: The matter is complex enough, maintaining more variants than absolutely necessary should be avoided.
Why not wait for a fix in the Java VM: Because even if/when it comes to Java 9/8/7, it will still require people to upgrade their VMs which is not a given at all.
Here is a first attempt to resolve this as simply as possible in principle: A modified version of the test sources that were submitted with the Java VM bug report.
I am simply wrapping the MyClassValue class with another instance of ClassValue that only has weak references to the MyClassValue instance.
This worked on Java 7 and 8. With Java 7 I saw used PermGen rise close to the configured maximum and then it was collected. With Java 8, Metaspace did not even rise, which is important because by default there is no maxium set for Metaspace.
{code:title=CVTest.java|java}
import java.lang.ClassValue;
import java.lang.ref.WeakReference;
import java.io.File;
import java.net.URLClassLoader;
import java.net.URL;
public class CVTest {
public static void main(String[] args) throws Throwable {
for (long i = 0; i<10000000; i++) {
File dir = new File("t/t.jar");
URLClassLoader classLoader = new URLClassLoader(new URL[]{dir.toURI().toURL()});
ClassValue cv = (ClassValue) classLoader.loadClass("MyClassValue").newInstance();
ClassValue cvWrapper = (ClassValue) classLoader.loadClass("MyClassValueWrapper")
.getConstructor(cv.getClass()).newInstance(cv);
Object value = cvWrapper.get(Integer.TYPE);
assert value != null;
assert value instanceof WeakReference;
Object innerValue = ((WeakReference)value).get();
assert innerValue != null;
assert innerValue.getClass().getClassLoader() == classLoader;
assert innerValue.getClass().getName().equals("MyClassValue$Dummy");
classLoader.close();
}
}
}
{code}
{code:title=MyClassValue.java|java}
import java.lang.ClassValue;
import java.lang.Class;
public class MyClassValue extends ClassValue {
static class Dummy {
static Object o;
}
protected Object computeValue(Class type) {
Dummy ret = new Dummy();
Dummy.o = this;
return ret;
}
public Object publicComputeValue(Class type) {
return computeValue(type);
}
}
{code}
{code:title=MyClassValueWrapper.java|java}
import java.lang.ref.WeakReference;
public class MyClassValueWrapper extends ClassValue {
private final WeakReference<MyClassValue> innerClassValueRef;
private WeakReference<Object> valueRef;
public MyClassValueWrapper(MyClassValue innerClassValue) {
this.innerClassValueRef = new WeakReference<MyClassValue>(innerClassValue);
}
protected Object computeValue(Class type) {
valueRef = new WeakReference<Object>(innerClassValueRef.get().publicComputeValue(type));
return valueRef;
}
}
{code}
I wrap the classes resulting from compiling MyClassValue and MyClassValueWrapper into t/t.jar and then run the test with "java -ea -XX:MaxMetaspaceSize=64m -cp . CVTest" resp. "java -ea -XX:MaxPermGenSize=64m -cp . CVTest".
I know that there is already much more specific work going on with regard to fixing these issues and there might be more issues with garbage collecting classes in the Groovy code - I just wanted to say that it might be good to strive for a solution with minimal complexity.)
> Use of ClassValue causes major memory leak
> ------------------------------------------
>
> Key: GROOVY-7591
> URL: https://issues.apache.org/jira/browse/GROOVY-7591
> Project: Groovy
> Issue Type: Improvement
> Affects Versions: 2.4.0, 2.4.1, 2.4.2, 2.4.3, 2.4.4
> Reporter: Cédric Champeau
> Assignee: Cédric Champeau
> Fix For: 2.4.5
>
>
> Following the discussion at http://mail-archives.apache.org/mod_mbox/incubator-groovy-dev/201509.mbox/%3CCADQzvm%3DvCHR7c1-uaCMkEq7i58ofvvaUrnqHjiGxMp0YQFuc5w%40mail.gmail.com%3E
> And the JDK bug https://bugs.openjdk.java.net/browse/JDK-8136353
> We suggest to disable use of ClassValue by default until bug is fixed in the JDK. There's a system property which will let the user reactivate use of ClassValue: {{groovy.use.classvalue}}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)