New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[native-image] Groovy script and missing InvokerHelper.runScript() method when building native image #708

Open
wololock opened this Issue Oct 3, 2018 · 0 comments

Comments

2 participants
@wololock

wololock commented Oct 3, 2018

Specs: GraalVM-1.0.0-RC7, Groovy 2.4.12

I'm trying to build native image of a simple "Hello, World!" Groovy script.

HelloWorld.groovy

#!groovy

println "Hello, World!"

It compiles:

groovyc HelloWorld.groovy

And runs as a Java program:

java -version
openjdk version "1.8.0_172"
OpenJDK Runtime Environment (build 1.8.0_172-20180625212755.graaluser.jdk8u-src-tar-g-b11)
GraalVM 1.0.0-rc7 (build 25.71-b01-internal-jvmci-0.48, mixed mode)

java -cp ".:$HOME/.m2/repository/org/codehaus/groovy/groovy-all/2.4.12/groovy-all-2.4.12.jar" HelloWorld
Hello, World!

Now, in the next step I tried building native image for GraalVM with the following command:

native-image -H:+ReportUnsupportedElementsAtRuntime -H:ReflectionConfigurationFiles=graal.json,groovy.json --no-server -cp ".:$HOME/.m2/repository/org/codehaus/groovy/groovy-all/2.4.12/groovy-all-2.4.12.jar" HelloWorld

where graal.json file (https://gist.github.com/wololock/923afb730a918d0d86ef14a4b5648220) lists all dynamically generated methods accessed via reflecion, and groovy.json simply adds HelloWorld class so GraalVM can locate its constructor:

[
  {
    "name": "HelloWorld",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true
  }
]

Image builds:

[helloworld:23841]    classlist:   2,750.39 ms
[helloworld:23841]        (cap):     802.15 ms
[helloworld:23841]        setup:   2,801.21 ms
Warning: Detected unnecessary RecomputeFieldValue.ArrayBaseOffset com.oracle.svm.core.jdk.Target_java_nio_DirectByteBuffer.arrayBaseOffset substitution field for java.nio.DirectByteBuffer.arrayBaseOffset. The annotated field can be removed. This ArrayBaseOffset computation can be detected automatically. Use option -H:+UnsafeAutomaticSubstitutionsLogLevel=2 to print all automatically detected substitutions. 
[helloworld:23841]   (typeflow):  14,050.77 ms
[helloworld:23841]    (objects):  11,259.90 ms
[helloworld:23841]   (features):     197.58 ms
[helloworld:23841]     analysis:  27,320.90 ms
[helloworld:23841]     universe:   1,034.53 ms
[helloworld:23841]      (parse):   3,799.24 ms
[helloworld:23841]     (inline):   3,542.06 ms
[helloworld:23841]    (compile):  16,638.90 ms
[helloworld:23841]      compile:  30,028.42 ms
[helloworld:23841]        image:   3,356.42 ms
[helloworld:23841]        write:     675.05 ms
[helloworld:23841]      [total]:  76,222.73 ms

But when I try to run it, it throws following exception:

./helloworld
Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: static org.codehaus.groovy.runtime.InvokerHelper.runScript() is applicable for argument types: (java.lang.Class, [Ljava.lang.String;) values: [class HelloWorld, [0, 10]]
	at java.lang.Throwable.<init>(Throwable.java:250)
	at java.lang.Exception.<init>(Exception.java:54)
	at java.lang.RuntimeException.<init>(RuntimeException.java:51)
	at groovy.lang.GroovyRuntimeException.<init>(GroovyRuntimeException.java:34)
	at groovy.lang.MissingMethodException.<init>(MissingMethodException.java:49)
	at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1501)
	at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1487)
	at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:53)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
	at HelloWorld.main(HelloWorld.groovy)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:163)

InvokeHelper class has a method for expected argument types - https://github.com/apache/groovy/blob/GROOVY_2_4_X/src/main/org/codehaus/groovy/runtime/InvokerHelper.java#L425

Two interesting facts:

  1. If I add a compiler configuration for groovyc and I force static compilation, native image runs without any issue.

compiler.groovy

withConfig(configuration) {
    ast(groovy.transform.CompileStatic)
    ast(groovy.transform.TypeChecked)
}
groovyc -configscript compiler.groovy HelloWorld.groovy
  1. If I switch from a Groovy script to a Groovy class (without static compilation), native image builds correctly and it runs without any issue.

The second case proved, that GraalVM can run a class created without static compilation. Groovy script gets compiled to a class, so technically it should be possible to run a script without static compilation. And here is what the script class looks like in Java (bytecode decompiled to a Java):

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import groovy.lang.Binding;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.callsite.CallSite;

public class HelloWorld extends Script {
    public HelloWorld() {
        CallSite[] var1 = $getCallSiteArray();
    }

    public HelloWorld(Binding context) {
        CallSite[] var2 = $getCallSiteArray();
        super(context);
    }

    public static void main(String... args) {
        CallSite[] var1 = $getCallSiteArray();
        var1[0].call(InvokerHelper.class, HelloWorld.class, args);
    }

    public Object run() {
        CallSite[] var1 = $getCallSiteArray();
        return var1[1].callCurrent(this, "Hello, World!");
    }
}

@wololock wololock changed the title from [native-image] Building an image from Groovy script throws groovy.lang.MissingMethodException: No signature of method: static org.codehaus.groovy.runtime.InvokerHelper.runScript() is applicable for argument types: (java.lang.Class, [Ljava.lang.String;) to [native-image] Groovy script and No signature of method: static org.codehaus.groovy.runtime.InvokerHelper.runScript() is applicable for argument types: (java.lang.Class, [Ljava.lang.String;) Oct 3, 2018

@wololock wololock changed the title from [native-image] Groovy script and No signature of method: static org.codehaus.groovy.runtime.InvokerHelper.runScript() is applicable for argument types: (java.lang.Class, [Ljava.lang.String;) to [native-image] Groovy script and missing InvokerHelper.runScript() when building native image Oct 3, 2018

@wololock wololock changed the title from [native-image] Groovy script and missing InvokerHelper.runScript() when building native image to [native-image] Groovy script and missing InvokerHelper.runScript() method when building native image Oct 3, 2018

@cstancu cstancu added the substrate label Oct 4, 2018

@cstancu cstancu self-assigned this Oct 4, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment