Tino Schöllhorn
Tino Schöllhorn

Reputation: 51

Groovy TemplateEngines and OutOfMemory. Possible memory leak?

I am having some trouble in using the Groovy TemplateEngines in Java without running in OOM. When creating a lot of different templates it seems to me that there a lot of scripts created on the heap - which are then never garbage collected.

I use java 8. When running this code with -Xmx32M there are about 3000 iterations possible. After that is a OOM-Error thrown.

Here is my code:

import groovy.text.SimpleTemplateEngine;
import groovy.text.Template;
import groovy.text.TemplateEngine;

import java.util.HashMap;
import java.util.Map;

public class Test {

    public static void main(String[] args) throws Exception {
        String groovy = "XX-${i}";

        for (int i = 0; i < (1000000000); i++) {
            TemplateEngine e = new SimpleTemplateEngine();

            Template t = e.createTemplate(groovy);

            Map<String, Object> binding = new HashMap<>();
            binding.put("i", i);

            String res = t.make(binding).toString();

            if (i % 100 == 0) {
                System.out.println("->" + res);
            }
        }
    }
}

I also tried different variations and ClassLoaded - but in essence the results are always the same. As I can't find any current issues with that I guess I am missing something.

Could anyone help to enlighten me?

Tino

Upvotes: 1

Views: 1268

Answers (3)

jpozorio
jpozorio

Reputation: 632

I have struggling with that problem has been a while and now I come up with that workaround.

Just call clear after run your script.

https://gist.github.com/jpozorio/38f26120e6346dfd74cecd7a147028aa

Upvotes: 0

VNN456
VNN456

Reputation: 147

Use Apache Commons Text. Fast and Efficient alternative to SimpleTemplateEngine.

String templateString, Map binding;
StrSubstitutor sb = new StrSubstitutor(binding);
String value = sb.replace(templateString);

Upvotes: 0

John Vint
John Vint

Reputation: 40256

Here is your problem https://bugs.openjdk.java.net/browse/JDK-8037342.

Each time the parser runs it creates a new unique class based off the number of parse being done. For instance, after a while the class names look like

groovy.runtime.metaclass.SimpleTemplateScript4237MetaClass groovy.runtime.metaclass.SimpleTemplateScript4238MetaClass

After a while the ClassLoader's parallelLockMap will fill the heap and nothing is eligible to be GC'd. It's sort of like a OOM PermGen error.

Upvotes: 2

Related Questions