Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
1.0-JSR-5
-
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.