Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-8113

Groovy script/template engine produce memory leak

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Critical
    • Resolution: Unresolved
    • 2.4.8
    • None
    • None
    • Groovy 2.4.8, Oracle Java JDK 8u121

    Description

      There is a simple way to produce OutOfMemoryException if run infinite numbers of groovy scripts or evaluate groovy templates.

      Simple test to reproduce a memory leak(run groovy script and make template inside the script):
      set max heap size: -Xmx7m

      import javax.script.*;
      import java.util.HashMap;
      import java.util.Map;
      
      public class OutOfMemoryTest {
      
      
          private static String TEMPLATE = "Dear ${fullName} please go away at ${time}";
      
          private static String SCRIPT = "def run(args) {\n" +
                  "def bindings = ['fullName' : 'Ali Baba', 'time' : new Date()]\n" +
                  "println args.templateEngine.createTemplate(args.template).make(bindings).toString()\n" +
                  "}";
      
          public static void main(String... args) {
      //        GroovySystem.getMetaClassRegistry().getMetaClassCreationHandler().setDisableCustomMetaClassLookup(true);
              while(true) {
                  ScriptEngineManager engineManager = new ScriptEngineManager();
                  ScriptEngine engine = engineManager.getEngineByName("groovy");
                  try {
                      engine.eval(SCRIPT);
                  } catch (ScriptException e) {
                      throw new RuntimeException(e);
                  }
                  groovy.text.SimpleTemplateEngine templateEngine = new groovy.text.SimpleTemplateEngine();
                  Invocable inv = (Invocable) engine;
                  Map<String, Object> params = new HashMap<>();
                  params.put("template", TEMPLATE);
                  params.put("templateEngine", templateEngine);
      
                  Object[] runArgs = { params };
                  try {
                      inv.invokeFunction("run", runArgs);
                  } catch (ScriptException | NoSuchMethodException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
      

      The main cause of issue is Java class loader. Two instances: sun.misc.Launcher.AppClassLoader and sun.misc.Launcher.ExtClassLoader (parent for first one), each of them has a strong reference:

      ConcurrentHashMap<String, Object> parallelLockMap
      

      It collects all loaded classes (and never releases their) for application including newly created script/template classes.
      The main reason of introduction of this reference described here: https://blogs.oracle.com/dholmes/entry/parallel_classloading_revisited_fully_concurrent

      For each iteration of my test I see that parallelLockMap grows with 6 new entries:

      groovy.runtime.metaclass.Script94MetaClass
      Script94BeanInfo
      Script94Customizer
      groovy.runtime.metaclass.SimpleTemplateScript94MetaClass
      SimpleTemplateScript94BeanInfo
      SimpleTemplateScript94Customizer
      

      See memory snapshots(attached): objects_explorer, merged_path.

      I have found a partial solution of the issue, if I add this code line to my test:

        GroovySystem.getMetaClassRegistry().getMetaClassCreationHandler().setDisableCustomMetaClassLookup(true);
      

      I see that classes like:

      groovy.runtime.metaclass.Script94MetaClass
      groovy.runtime.metaclass.SimpleTemplateScript94MetaClass
      

      goes away (groovy engine don't ask ClassLoader to find this classes on class path therefore such classes are not collected by ClassLoader) but classes like

      Script94BeanInfo
      Script94Customizer
      SimpleTemplateScript94BeanInfo
      SimpleTemplateScript94Customizer
      

      still has affect on memory.

      Dear developers, could you please point me any advice/workarounds for this issue. It will be fine to get rig this issue in future releases.

      Attachments

        1. merged_path.png
          362 kB
          Artyom Kravchenko
        2. object_explorer.png
          376 kB
          Artyom Kravchenko

        Issue Links

          Activity

            People

              Unassigned Unassigned
              Artyom Artyom Kravchenko
              Votes:
              2 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

                Created:
                Updated: