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

Type '[I' is not assignable to reference type when using Groovy 3.0.10

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 3.0.10
    • 2.5.17, 3.0.11, 4.0.2
    • None
    • None

    Description

      We are having a strange problem when using static compile transformation.

      Most likely what we are doing is not the best approach. However, this was working in 3.0.9 and stopped working with 3.0.10.

      If we take this main class:

      package org.example;
      
      import java.util.Collections;
      import java.util.HashMap;
      import java.util.Map;
      
      import javax.script.Bindings;
      import javax.script.ScriptEngine;
      import javax.script.ScriptException;
      import javax.script.SimpleBindings;
      
      import org.codehaus.groovy.ast.ClassHelper;
      import org.codehaus.groovy.ast.ClassNode;
      import org.codehaus.groovy.control.CompilerConfiguration;
      import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
      import org.codehaus.groovy.jsr223.GroovyScriptEngineImpl;
      
      import groovy.lang.GroovyClassLoader;
      import groovy.transform.CompileStatic;
      
      public class GroovyProblemExample {
      
          public static final String VAR_TYPES = "variable.types";
      
          public static final ThreadLocal<Map<String, Object>> COMPILE_OPTIONS = new ThreadLocal<>();
      
          public static void main(String[] args) throws ScriptException {
              ScriptEngine scriptEngine = new GroovyScriptEngineImpl(createClassLoader());
              String script = ""
                      + "int sum = 0\n"
                      + "for ( i in inputArray ) {\n"
                      + "    sum += i\n"
                      + "}\n"
                      + "execution.setVariable(\"sum\", sum)";
              Map<String, Object> input = new HashMap<>();
              TestExecution execution = new TestExecution();
      
              int[] inputArray = new int[] { 1, 2, 3, 4, 5 };
              input.put("inputArray", inputArray);
              input.put("execution", execution);
              Bindings bindings = createBindings(input);
      
              COMPILE_OPTIONS.remove();
              Map<String, ClassNode> variableTypes = new HashMap<>();
              for (Map.Entry<String, Object> entry : bindings.entrySet()) {
                  variableTypes.put(entry.getKey(),
                          ClassHelper.make(entry.getValue().getClass()));
              }
      
              variableTypes.put("execution", ClassHelper.make(TestExecution.class));
              Map<String, Object> options = new HashMap<>();
              options.put(VAR_TYPES, variableTypes);
              COMPILE_OPTIONS.set(options);
      
              scriptEngine.eval(script, bindings);
      
              System.out.println(execution.getVariable("sum"));
          }
      
          public static Bindings createBindings(Map<String, Object> parameters) {
              return new SimpleBindings(parameters);
          }
      
          public static GroovyClassLoader createClassLoader() {
              return new GroovyClassLoader(GroovyProblemExample.class.getClassLoader(), createStaticConfiguration(), true);
          }
      
          protected static CompilerConfiguration createStaticConfiguration() {
              CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
              ASTTransformationCustomizer astTransformationCustomizer = new ASTTransformationCustomizer(
                      Collections.singletonMap("extensions", Collections.singletonList("ExampleExtension.groovy")),
                      CompileStatic.class, "org.codehaus.groovy.transform.sc.StaticCompileTransformation");
              compilerConfiguration.addCompilationCustomizers(astTransformationCustomizer);
              return compilerConfiguration;
          }
      
          public static class TestExecution {
      
              protected final Map<String, Object> data = new HashMap<>();
      
              public void setVariable(String name, Object value) {
                  data.put(name, value);
              }
      
              public Object getVariable(String name) {
                  return data.get(name);
              }
          }
      
      }
      

      and this extension:

      import static org.example.GroovyProblemExample.COMPILE_OPTIONS
      import static org.example.GroovyProblemExample.VAR_TYPES
      
      def typesOfVariables = COMPILE_OPTIONS.get()[VAR_TYPES]
      
      unresolvedVariable { var ->
          if (typesOfVariables[var.name]) {
              return makeDynamic(var, typesOfVariables[var.name])
          }
      }
      

      Running the main class with Groovy 3.0.9 we have 15 printed out in the console. However, running it with 3.0.10 we get the following error:

      Exception in thread "main" java.lang.VerifyError: Bad type on operand stack in aaload
      Exception Details:
        Location:
          Script1.run()Ljava/lang/Object; @54: aaload
        Reason:
          Type '[I' (current frame, stack[0]) is not assignable to reference type
        Current Frame:
          bci: @54
          flags: { }
          locals: { 'Script1', '[Lorg/codehaus/groovy/runtime/callsite/CallSite;', integer, top, '[I', integer, integer }
          stack: { '[I', integer }
        Bytecode:
          0000000: 00b8 0024 4c03 3d1c 5701 4e2b 1225 322a
          0000010: b900 2b02 0059 122d b800 33c0 002d 3a04
          0000020: c600 2719 04be 3605 0336 0615 0615 05a2
          0000030: 0018 1904 1506 324e 8406 011c 2db8 0039
          0000040: 6059 3d57 a7ff e72b 123a 322a b900 2b02
          0000050: 00c0 003c 123e 1cb8 0044 b600 4801 b0  
        Stackmap Table:
          full_frame(@43,{Object[#2],Object[#77],Integer,Top,Object[#45],Integer,Integer},{})
          chop_frame(@71,2)
      
      	at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
      	at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3373)
      	at java.base/java.lang.Class.getConstructor0(Class.java:3578)
      	at java.base/java.lang.Class.getConstructor(Class.java:2271)
      	at org.codehaus.groovy.runtime.InvokerHelper.newScript(InvokerHelper.java:502)
      	at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:461)
      	at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:266)
      	at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:155)
      	at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:231)
      	at org.example.GroovyProblemExample.main(GroovyProblemExample.java:55)
      

      This happens with Java 17 and Java 11.

      This is a simplified example that is taken from something that we have in the Flowable Engine (https://github.com/flowable/flowable-engine/tree/main/modules/flowable-groovy-script-static-engine).

      Attachments

        Activity

          People

            emilles Eric Milles
            filiphr Filip Hrisafov
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: