Groovy ScriptEngine memory leak – fixed

Java 6 includes built-in support for Scripting for the Java Platform (JSR 223). You can learn how to use this scripting support with Groovy in the Grovvy documentation.

We use this Groovy scripting support in a real production environment for customizing a price calculation algorithm. The customizing scripts are stored in the database and we load one of these scripts each time before calculating a price. Because the script is loaded from the database a new String instance is used for each calculation. This causes an OutOfMemoryExcpetion in our application after some time. This is because the implementation of the Groovy ScriptEngine creates a new Class object for each script execution.

You can reproduce this OutOfMemoryExcpetion with the following java code:

ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine engine = m.getEngineByName("groovy");
while (true) {
  engine.eval(new String("return 'memory leak'"));

This simple java snippet causes a memory leak because the internal caching of the compiled scripts has been changed since Groovy 2.0. The script “return ‘memory leak'” will be compiled to a new Class instance in every loop execution and this instance cannot be removed by the garbage collector.

But there is a simple way of fixing this memory leak:

engine.eval(new String("return 'memory leak'").intern());

Just use the intern() method of String to get “a canonical representation for the string object”. Then the script engine cache determines the script and it should be no recompilation any more.

Short URL for this post:
This entry was posted in Groovy and Grails and tagged , , , . Bookmark the permalink.

2 Responses to Groovy ScriptEngine memory leak – fixed

  1. Thanks, for sharing this useful information with us!

  2. Hi – thanks for this. Just spent two hours arriving at this same conclusion, then searched for GroovyScriptEngine and intern() and found this. I wonder why this has been changed – seems counter-intuitive.

Leave a Reply

Your email address will not be published. Required fields are marked *