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

each invocation of run on GroovyScriptEngine don't share same GroovyClassLoader

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.0-JSR-5
    • 1.1-beta-1
    • class generator
    • None
    • Patch

    Description

      User.groovy
      ------------------
      class User {
      def String name
      }

      Step1.groovy
      ------------------
      Me = new User ()
      Me.name = 'Me'

      Step2.groovy
      -------------------
      You = new User ()
      You.name = 'You'

      System.out.println "${Me.name} is ${Me.class} and ${You.name} is ${You.class}"
      assert You.class == Me.class

      TestClassCast.java
      ----------------------------
      import java.io.File;
      import groovy.lang.Binding;
      import groovy.util.GroovyScriptEngine;

      public class TestClassCast {
      public TestClassCast () { }

      public static void main(String[] args) throws Throwable {
      Binding binding = new Binding();

      String [] paths =

      { "." }

      ;
      GroovyScriptEngine gse = new GroovyScriptEngine (paths);
      gse.run ("Step1.groovy", binding);
      gse.run ("Step2.groovy", binding);
      }
      }

      Executing this java program will result in:

      Me is class User and You is class User
      Exception in thread "main" java.lang.AssertionError: Expression: (You.class == Me.class)
      at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:406)
      at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(ScriptBytecodeAdapter.java:725)
      at Step2.run(Step2.groovy:5)
      at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:378)
      at TestClassCast.main(TestClassCast.java:14)

      However executing Step1.groovy followed by Step2.groovy in groovysh will not generate an AssertionError. Also pre-compiling User.groovy doesn't generate this error.

      Investigation shows that while running a script, GroovyScriptEngine creates a new GroovyClassLoader at each run in updateCacheEntry, therefore any classes loaded by every invocation of the GSE won't share the same GroovyClassLoader.

      This patch remedies that problem by only allocating one GroovyClassLoader per instantiation of GSE and deprecating any changes of the parentClassLoader of GSE. However I left this ability to prevent code breakage outside of groovy-code.

      After a few releases we should make groovyLoader final and assign it in a constructor.

      Attachments

        1. GroovyScriptEngine.patch
          11 kB
          Pascal Demilly

        Activity

          People

            guillaume Guillaume Sauthier
            pdemilly Pascal Demilly
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: