[groovy-user] java.lang.OutOfMemoryError

23 views
Skip to first unread message

Dirk Wellmann

unread,
Nov 23, 2007, 12:10:13 PM11/23/07
to us...@groovy.codehaus.org
Hi List,

I'm new to groovy and used it in a actual Project, but using
GroovyShell's evaluate - Methods results after a few thousand calls in
an OutOfMemoryException, here is a little Exampel-code witch produces
this Error: (I'm useing the 1.0 stable Release, but bis 1.1RC1 I've got
the same Problem)

What's my Mistake or is it a Bug?

Code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package de.pip.qvis.util;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author dw
*/
public class TestStuff {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Binding lvBinding = new Binding();
GroovyShell lvGroovy = new GroovyShell(lvBinding);

try {

int round=0;

while(true)
{
// TODO code application logic here
lvBinding.setVariable("message", "Roundtripp [" + round++ +
"] is reached.");

String lvScript = "return \"Hello World \" + message;";
System.out.println(lvGroovy.evaluate(lvScript));
}
} catch (Exception ex) {
Logger.getLogger(TestStuff.class.getName()).log(Level.SEVERE,
null, ex);
System.err.println(ex);
ex.printStackTrace();
}


}

}

Exception:
Hello World Roundtripp [8573] is reached.
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
at
org.codehaus.groovy.runtime.ReflectorLoader.defineClass(ReflectorLoader.java:71)
at groovy.lang.MetaClassRegistry$3.run(MetaClassRegistry.java:256)
at java.security.AccessController.doPrivileged(Native Method)
at
groovy.lang.MetaClassRegistry.loadReflector(MetaClassRegistry.java:254)
at
groovy.lang.MetaClassImpl.generateReflector(MetaClassImpl.java:2002)
at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:1884)
at
groovy.lang.MetaClassRegistry.getMetaClass(MetaClassRegistry.java:136)
at org.codehaus.groovy.runtime.Invoker.getMetaClass(Invoker.java:78)
at
org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:94)
at
groovy.lang.GroovyObjectSupport.<init>(GroovyObjectSupport.java:61)
at groovy.lang.Script.<init>(Script.java:66)
at Script8575.<init>(Script8575.groovy)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at
org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:421)
at groovy.lang.GroovyShell.parse(GroovyShell.java:525)
at groovy.lang.GroovyShell.parse(GroovyShell.java:505)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:483)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:459)
at de.pip.qvis.util.TestStuff.main(TestStuff.java:36)

--
Regards Dirk

Dirk Wellmann


---------------------------------------------------------------------
To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Jim White

unread,
Nov 23, 2007, 1:05:10 PM11/23/07
to us...@groovy.codehaus.org
Dirk Wellmann wrote:

> Hi List,
>
> I'm new to groovy and used it in a actual Project, but using
> GroovyShell's evaluate - Methods results after a few thousand calls in
> an OutOfMemoryException, here is a little Exampel-code witch produces
> this Error: (I'm useing the 1.0 stable Release, but bis 1.1RC1 I've got
> the same Problem)
>
> What's my Mistake or is it a Bug?

> ...

You're encountering the dreaded ClassLoader leak. I don't yet know how
to workaround it other than increasing memory until your program can
finish. The same situation exists with the Groovy Ant task and I hope
to find how to fix this eventually.

http://blogs.sun.com/fkieviet/entry/classloader_leaks_the_dreaded_java

Jim

Dirk Wellmann

unread,
Nov 23, 2007, 1:50:43 PM11/23/07
to us...@groovy.codehaus.org
Hi Jim,

thx for your fast response, I implementet a fix - I would call it a very
dirty Workarround. I've a usage-counter and if it reaches 1000 I make a
new Instance of GroovyShell / GroovyScriptingEngine, that seems to work.
I'm testing on it.

Exampel is now:
package de.pip.qvis.util;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author dw
*/
public class TestStuff {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Binding lvBinding = new Binding();
GroovyShell lvGroovy = new GroovyShell(lvBinding);

try {

int round=0;

int ncount=1000;



while(true)
{
// TODO code application logic here
lvBinding.setVariable("message", "Roundtripp [" + round++ +
"] is reached.");

ncount--;

if(ncount == 0)
{
lvGroovy = new GroovyShell(lvBinding);
ncount=1000;
}

String lvScript = "return \"Hello World \" + message;";
System.out.println(lvGroovy.evaluate(lvScript));
}
} catch (Exception ex) {
Logger.getLogger(TestStuff.class.getName()).log(Level.SEVERE,
null, ex);
System.err.println(ex);
ex.printStackTrace();
}


}

}


Regards Dirk

Jim White schrieb:


--
Viele Gruesse

Dirk Wellmann
- - - - - - - - - - - - - - - - - - -
PIP The Webapplication Company
Dirk Wellmann
Hersteller Str. 9
37688 Beverungen
fon. : +4932229174242 (VOIP)
fon. : +495273210330
mobil: +491725267208
skype: dirk.wellmann
mail : d...@piponline.net

Guillaume Laforge

unread,
Nov 23, 2007, 2:21:27 PM11/23/07
to us...@groovy.codehaus.org
When creating lots of short-lived classes, it's a good practice to
discard the shell or classloader, otherwise, you'll run into memory
issues.
It's a bit like if you had a list, and you make a while loop to add
more and more elements to the list, and in the end, obviously, you'll
hit a memory limit.

--
Guillaume Laforge
Groovy Project Manager
G2One, Inc. Vice-President Technology
http://www.g2one.com

Dirk Wellmann

unread,
Nov 23, 2007, 2:32:25 PM11/23/07
to us...@groovy.codehaus.org
Hi, Guillaume Laforge,

yes ok I understand that, but making every cycle a new Instance is much
to expensive (Performance). I use groovy-Scripts to give my users a
chance to generate dynamic Content. Maybe I use Groovy in a false way? I
think of impementing it an other way, but this would be not so
comfortable for my users - i will load a groovy-Script while making a
instance of my ContentProvider, the Script will then be compiled once
and then used many times until the Script-file changes on disk - but
then the user has to edit in two Places. Hmm I will sleep over it.

Regards Dirk

Guillaume Laforge schrieb:

Jim White

unread,
Nov 23, 2007, 3:18:47 PM11/23/07
to us...@groovy.codehaus.org
What I do (in GroovyForOpenOffice) is to cache the GroovyShell and the
compiled script for each macro. If the macro gets updated then I reuse
the GroovyShell and just recompile the script. There is also a method
for purging classes generated by a script (which is used automatically
when you use the evaluate rather than compile method).

Jim

Dirk Wellmann

unread,
Nov 23, 2007, 10:34:55 PM11/23/07
to us...@groovy.codehaus.org
Hi Jim,

of course, but I used the evaluate - method, but I ran into trouble. Now
Test runs for 7 Hours fine and every 1000 cycels I make a new Instance
of QroovyShell. Beside, what Method should I call to purge older Classes?

Regards Dirk

Jim White schrieb:

cmay4

unread,
Nov 26, 2007, 3:56:15 PM11/26/07
to us...@groovy.codehaus.org

Your solution works fine under 1.0, but will still run out of memory in the
1.1rc2 build. I have run into the same issue as you and mine will work fine
under 1.0 but quickly runs out of PermGen in 1.1rc2. Hopefully it will be
resolved before the release of 1.1.

Here is my simple example which recreates the GroovyShell each time:

int counter = 0;
while (true) {
counter++;

String expression = "return " + counter;

// parse and execute expression
Script script = new GroovyShell().parse(expression);
Object obj = script.run();

System.out.println(expression + ": " + obj);
}

Chuck


Dirk Wellmann wrote:
>
> Hi Jim,
>
> of course, but I used the evaluate - method, but I ran into trouble. Now
> Test runs for 7 Hours fine and every 1000 cycels I make a new Instance
> of QroovyShell. Beside, what Method should I call to purge older Classes?
>
> Regards Dirk
>

--
View this message in context: http://www.nabble.com/java.lang.OutOfMemoryError-tf4862836.html#a13958584
Sent from the groovy - user mailing list archive at Nabble.com.

Jochen Theodorou

unread,
Nov 26, 2007, 6:57:41 PM11/26/07
to us...@groovy.codehaus.org
cmay4 schrieb:

> Your solution works fine under 1.0, but will still run out of memory in the
> 1.1rc2 build. I have run into the same issue as you and mine will work fine
> under 1.0 but quickly runs out of PermGen in 1.1rc2. Hopefully it will be
> resolved before the release of 1.1.
>
> Here is my simple example which recreates the GroovyShell each time:
>
> int counter = 0;
> while (true) {
> counter++;
>
> String expression = "return " + counter;
>
> // parse and execute expression
> Script script = new GroovyShell().parse(expression);
> Object obj = script.run();
>
> System.out.println(expression + ": " + obj);
> }

that is an important information... because earlier (pre 1.0) we had
problems like these and it was the MetaClassRegistry causing this
problem. So I first checked the registry and it is still looking good.
It also tells me that your VM version is ok with collecting the classes,
some VM versions had problems with doing so.

what we did change the most is the Reflection cache... and looking at it
it is now clear to me why you have that problem. CACHED_CLASS_MAP uses
classes as keys, leading to this problem.. ok, no problem, let us make a
weak hashmap out of it... oh, and a weak version for assignableMap too
and then.. looks like it works then.

ok, fixed... at last here this works now. Btw, there are several things
I wanted to tell... you can remove the classes from GroovyShell by

shell.getClassLoader().clearCache()

GroovyClassLoader is no ordenary classloader.. and If you use the
GroovyShell#parse(String expression, String name), then you won't need
to that too as long as the name is always the same. The code would be then:

> int counter = 0;
> GroovyShell shell = new GroovyShell();

> while (true) {
> counter++;
>
> String expression = "return " + counter;
>
> // parse and execute expression

> Script script = shell.parse(expression,"x.groovy");


> Object obj = script.run();
>
> System.out.println(expression + ": " + obj);
> }

bye blackdrag


--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

Reply all
Reply to author
Forward
0 new messages