Skip to content
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 closure coercion to functional interface throws UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandle.bindTo(Object) #1306

Closed
wololock opened this issue May 20, 2019 · 3 comments
Assignees

Comments

@wololock
Copy link

wololock commented May 20, 2019

Affected version: GraalVM CE 19.0.0

Context: Native image generation fails when we use a Groovy closure in place of a functional interface (or single abstract method class). This is one of the most popular Groovy idioms which allows us to put a closure in place of a Java's lambda expression (Groovy 2.x parser does not support lambda expressions). The simple example may look like this:

package example

import java.util.function.IntPredicate
import java.util.stream.IntStream

class App {
    static void main(String[] args) {
        def result = IntStream.range(0, 100)
                .filter { int n -> n > 10 }
                .sum()

        println "result = ${result}"
    }
}

In this example, we pass a closure { int n -> n > 10 } in place of a IntPredicate functional interface. The bytecode generated from that Groovy code looks like this after decompiling to the Java code:

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

package example;

import groovy.lang.Closure;
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.transform.Generated;
import java.util.function.IntPredicate;
import java.util.stream.IntStream;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.GStringImpl;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;

public class App implements GroovyObject {
    @Generated
    public App() {
        MetaClass var1 = this.$getStaticMetaClass();
        this.metaClass = var1;
    }

    public static void main(String... args) {
        final class _main_closure1 extends Closure implements GeneratedClosure {
            public _main_closure1(Object _outerInstance, Object _thisObject) {
                super(_outerInstance, _thisObject);
            }

            public Object doCall(int n) {
                return n > 10;
            }

            public Object call(int n) {
                return this.doCall(n);
            }
        }

        int result = IntStream.range(0, 100).filter((IntPredicate)ScriptBytecodeAdapter.castToType(new _main_closure1(App.class, App.class), IntPredicate.class)).sum();
        DefaultGroovyMethods.println(App.class, new GStringImpl(new Object[]{result}, new String[]{"result = ", ""}));
        Object var10000 = null;
    }
}

This class was compiled with the static compilation enabled.

Code sample: https://github.com/wololock/graalvm-groovy-closures

How to reproduce:

$ git clone https://github.com/wololock/graalvm-groovy-closures

$ cd graalvm-groovy-closures 

$ ./gradlew --no-daemon shadowJar

$ ./build-native-image.sh

The build-native-image.sh looks like this:

native-image --allow-incomplete-classpath \
    -H:+AllowVMInspection \
    -H:+ReportUnsupportedElementsAtRuntime \
    -H:ConfigurationFileDirectories=config/native-image/ \
    --initialize-at-build-time \
    --initialize-at-run-time=org.codehaus.groovy.control.XStreamUtils,groovy.grape.GrapeIvy \
    --no-fallback \
    --no-server \
    -H:+ReportExceptionStackTraces \
    -jar build/libs/graalvm-groovy-closures-all.jar

After running shadowJar task, Gradle runs the application from generated JAR file using GraalVM's native-image-agent to generate a reflection configuration file in config/native-image folder, and it removes java.lang.reflect.Executable from JSON file as explained in #1260

Native image generation fails with the following output:

[graalvm-groovy-closures-all:29306]    classlist:   2,505.95 ms
[graalvm-groovy-closures-all:29306]        (cap):     981.41 ms
[graalvm-groovy-closures-all:29306]        setup:   2,169.78 ms
[graalvm-groovy-closures-all:29306]     analysis:  43,945.08 ms
Error: Unsupported features in 5 methods
Detailed message:
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandle.bindTo(Object)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:221)
Call path from entry point to java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandle, MethodType, boolean, boolean): 
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:207)
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:194)
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:380)
	at java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:776)
	at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandleImpl$BindCaller.prepareForInvoker(MethodHandle)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1166)
Call path from entry point to java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(Class): 
	at java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1141)
	at java.lang.invoke.MethodHandleImpl$BindCaller.access$300(MethodHandleImpl.java:1122)
	at java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1175)
	at java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1173)
	at com.oracle.svm.core.jdk.Target_java_lang_ClassValue.get(JavaLangSubstitutions.java:512)
	at org.codehaus.groovy.reflection.ClassInfo.getClassInfo(ClassInfo.java:170)
	at org.codehaus.groovy.reflection.ReflectionCache.getCachedClass(ReflectionCache.java:95)
	at groovy.lang.Closure.<init>(Closure.java:216)
	at example.App$_main_closure1.<init>(App.groovy)
	at example.App.main(App.groovy:8)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:153)
	at com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_5087f5482cc9a6abc971913ece43acb471d2631b(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandleImpl.buildVarargsArray(MethodHandle, MethodHandle, int)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl.varargsArray(MethodHandleImpl.java:1634)
Call path from entry point to java.lang.invoke.MethodHandleImpl.varargsArray(Class, int): 
	at java.lang.invoke.MethodHandleImpl.varargsArray(MethodHandleImpl.java:1611)
	at java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle.asCollector(MethodHandleImpl.java:1363)
	at java.lang.invoke.MethodHandleImpl$AsVarargsCollector.asTypeUncached(MethodHandleImpl.java:502)
	at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: type is not available in this platform: org.graalvm.nativeimage.hosted.Feature$DuringAnalysisAccess
Trace: 	object java.lang.Class[]
	object java.lang.invoke.MethodType
	object java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
	object java.util.concurrent.ConcurrentHashMap$Node
	object java.util.concurrent.ConcurrentHashMap$Node
	object java.util.concurrent.ConcurrentHashMap$Node[]
	object java.util.concurrent.ConcurrentHashMap
	object java.lang.invoke.MethodType$ConcurrentWeakInternSet
	method java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean)
Call path from entry point to java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean): 
	at java.lang.invoke.MethodType.makeImpl(MethodType.java:301)
	at java.lang.invoke.MethodType.genericMethodType(MethodType.java:338)
	at java.lang.invoke.MethodType.genericMethodType(MethodType.java:356)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:626)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: type is not available in this platform: org.graalvm.nativeimage.impl.ImageSingletonsSupport

com.oracle.svm.core.util.UserError$UserException: Unsupported features in 5 methods
Detailed message:
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandle.bindTo(Object)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:221)
Call path from entry point to java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandle, MethodType, boolean, boolean): 
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:207)
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:194)
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:380)
	at java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:776)
	at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandleImpl$BindCaller.prepareForInvoker(MethodHandle)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1166)
Call path from entry point to java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(Class): 
	at java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1141)
	at java.lang.invoke.MethodHandleImpl$BindCaller.access$300(MethodHandleImpl.java:1122)
	at java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1175)
	at java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1173)
	at com.oracle.svm.core.jdk.Target_java_lang_ClassValue.get(JavaLangSubstitutions.java:512)
	at org.codehaus.groovy.reflection.ClassInfo.getClassInfo(ClassInfo.java:170)
	at org.codehaus.groovy.reflection.ReflectionCache.getCachedClass(ReflectionCache.java:95)
	at groovy.lang.Closure.<init>(Closure.java:216)
	at example.App$_main_closure1.<init>(App.groovy)
	at example.App.main(App.groovy:8)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:153)
	at com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_5087f5482cc9a6abc971913ece43acb471d2631b(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandleImpl.buildVarargsArray(MethodHandle, MethodHandle, int)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl.varargsArray(MethodHandleImpl.java:1634)
Call path from entry point to java.lang.invoke.MethodHandleImpl.varargsArray(Class, int): 
	at java.lang.invoke.MethodHandleImpl.varargsArray(MethodHandleImpl.java:1611)
	at java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle.asCollector(MethodHandleImpl.java:1363)
	at java.lang.invoke.MethodHandleImpl$AsVarargsCollector.asTypeUncached(MethodHandleImpl.java:502)
	at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: type is not available in this platform: org.graalvm.nativeimage.hosted.Feature$DuringAnalysisAccess
Trace: 	object java.lang.Class[]
	object java.lang.invoke.MethodType
	object java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
	object java.util.concurrent.ConcurrentHashMap$Node
	object java.util.concurrent.ConcurrentHashMap$Node
	object java.util.concurrent.ConcurrentHashMap$Node[]
	object java.util.concurrent.ConcurrentHashMap
	object java.lang.invoke.MethodType$ConcurrentWeakInternSet
	method java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean)
Call path from entry point to java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean): 
	at java.lang.invoke.MethodType.makeImpl(MethodType.java:301)
	at java.lang.invoke.MethodType.genericMethodType(MethodType.java:338)
	at java.lang.invoke.MethodType.genericMethodType(MethodType.java:356)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:626)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: type is not available in this platform: org.graalvm.nativeimage.impl.ImageSingletonsSupport

	at com.oracle.svm.core.util.UserError.abort(UserError.java:75)
	at com.oracle.svm.hosted.FallbackFeature.reportAsFallback(FallbackFeature.java:218)
	at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:733)
	at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:523)
	at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:441)
	at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Unsupported features in 5 methods
Detailed message:
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandle.bindTo(Object)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:221)
Call path from entry point to java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandle, MethodType, boolean, boolean): 
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:207)
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:194)
	at java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:380)
	at java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:776)
	at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandleImpl$BindCaller.prepareForInvoker(MethodHandle)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1166)
Call path from entry point to java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(Class): 
	at java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1141)
	at java.lang.invoke.MethodHandleImpl$BindCaller.access$300(MethodHandleImpl.java:1122)
	at java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1175)
	at java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1173)
	at com.oracle.svm.core.jdk.Target_java_lang_ClassValue.get(JavaLangSubstitutions.java:512)
	at org.codehaus.groovy.reflection.ClassInfo.getClassInfo(ClassInfo.java:170)
	at org.codehaus.groovy.reflection.ReflectionCache.getCachedClass(ReflectionCache.java:95)
	at groovy.lang.Closure.<init>(Closure.java:216)
	at example.App$_main_closure1.<init>(App.groovy)
	at example.App.main(App.groovy:8)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:153)
	at com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_5087f5482cc9a6abc971913ece43acb471d2631b(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandleImpl.buildVarargsArray(MethodHandle, MethodHandle, int)
Trace: 
	at parsing java.lang.invoke.MethodHandleImpl.varargsArray(MethodHandleImpl.java:1634)
Call path from entry point to java.lang.invoke.MethodHandleImpl.varargsArray(Class, int): 
	at java.lang.invoke.MethodHandleImpl.varargsArray(MethodHandleImpl.java:1611)
	at java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle.asCollector(MethodHandleImpl.java:1363)
	at java.lang.invoke.MethodHandleImpl$AsVarargsCollector.asTypeUncached(MethodHandleImpl.java:502)
	at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: type is not available in this platform: org.graalvm.nativeimage.hosted.Feature$DuringAnalysisAccess
Trace: 	object java.lang.Class[]
	object java.lang.invoke.MethodType
	object java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
	object java.util.concurrent.ConcurrentHashMap$Node
	object java.util.concurrent.ConcurrentHashMap$Node
	object java.util.concurrent.ConcurrentHashMap$Node[]
	object java.util.concurrent.ConcurrentHashMap
	object java.lang.invoke.MethodType$ConcurrentWeakInternSet
	method java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean)
Call path from entry point to java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean): 
	at java.lang.invoke.MethodType.makeImpl(MethodType.java:301)
	at java.lang.invoke.MethodType.genericMethodType(MethodType.java:338)
	at java.lang.invoke.MethodType.genericMethodType(MethodType.java:356)
	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:626)
	at org.codehaus.groovy.vmplugin.v7.Java7.invokeHandle(Java7.java:106)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:110)
	at com.sun.proxy.$Proxy126.hashCode(Unknown Source)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.get(HashMap.java:557)
	at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:123)
	at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:325)
	at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
Error: type is not available in this platform: org.graalvm.nativeimage.impl.ImageSingletonsSupport

	at com.oracle.graal.pointsto.constraints.UnsupportedFeatures.report(UnsupportedFeatures.java:133)
	at com.oracle.graal.pointsto.BigBang.finish(BigBang.java:564)
	at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:684)
	... 7 more
Error: Image build request failed with exit status 1

Cédric Champeau (the author of Groovy static compiler) documented this issue on his blog some time ago - https://melix.github.io/blog/2019/03/simple-http-server-graal.html I'm posting it here so you can get a better context.

Anonymous classes

You can also find a use case with anonymous classes in the sample Groovy code. Using an anonymous class in place of the closure compiles to the native image. The bytecode of a Groovy class using an anonymous class instead of a closure decompiled to the Java looks like this:

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

package example;

import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.transform.Generated;
import java.util.function.IntPredicate;
import java.util.stream.IntStream;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.GStringImpl;

public class App implements GroovyObject {
    @Generated
    public App() {
        MetaClass var1 = this.$getStaticMetaClass();
        this.metaClass = var1;
    }

    public static void main(String... args) {
        class NamelessClass_1 implements IntPredicate, GroovyObject {
            public boolean test(int n) {
                return n > 10;
            }
        }

        int result = IntStream.range(0, 100).filter(new NamelessClass_1(App.class)).sum();
        DefaultGroovyMethods.println(App.class, new GStringImpl(new Object[]{result}, new String[]{"result = ", ""}));
        Object var10000 = null;
    }
}

And here is the log of compiling and running the example with an anonymous class instead of a closure.

$ ./build-native-image.sh              
Compiling GraalVM native image...
[graalvm-groovy-closures-all:11315]    classlist:   2,627.08 ms
[graalvm-groovy-closures-all:11315]        (cap):     867.55 ms
[graalvm-groovy-closures-all:11315]        setup:   2,132.43 ms
[graalvm-groovy-closures-all:11315]   (typeflow):  13,515.41 ms
[graalvm-groovy-closures-all:11315]    (objects):  13,742.11 ms
[graalvm-groovy-closures-all:11315]   (features):     433.35 ms
[graalvm-groovy-closures-all:11315]     analysis:  28,160.12 ms
[graalvm-groovy-closures-all:11315]     (clinit):     486.25 ms
[graalvm-groovy-closures-all:11315]     universe:   1,354.30 ms
[graalvm-groovy-closures-all:11315]      (parse):   2,661.01 ms
[graalvm-groovy-closures-all:11315]     (inline):   3,634.41 ms
[graalvm-groovy-closures-all:11315]    (compile):  20,239.78 ms
[graalvm-groovy-closures-all:11315]      compile:  28,116.95 ms
[graalvm-groovy-closures-all:11315]        image:   2,730.84 ms
[graalvm-groovy-closures-all:11315]        write:     365.21 ms
[graalvm-groovy-closures-all:11315]      [total]:  65,647.49 ms

$ ./graalvm-groovy-closures-all 
result = 4895

It feels like this use case should be supported by the native image generation. Maybe supporting Groovy closures in this context requires some subtraction using SubstrateVM SDK? I can run some experiments, but I would need some guidance on where to start.

Thanks in advance!

@viktorklang
Copy link

I just ran into this with Scala closures/lambdas.

@wololock
Copy link
Author

UPDATE: I can confirm that using the OpenJDK 11 variant of GraalVM CE 20.2.0 compiles to the native image and it works as expected. (I tested both Groovy 3.0.5 and Groovy 2.5.10.) The OpenJDK 8u262 one fails at the compilation with the same error as mentioned above.

@cstancu
Copy link
Member

cstancu commented Sep 22, 2020

Thanks for the detailed reproducible. The underlying issue here is incomplete MethodHandle support. That is under development and is being tracked by #2761.

@cstancu cstancu closed this as completed Sep 22, 2020
dmurat added a commit to croz-ltd/klokwrk-project that referenced this issue Jan 3, 2021
It turns out that GraalVM JDK 8 version (sdkman version: 20.3.0.r8-grl) works.
Previously I had a constraint because of oracle/graal#1306
Obviously it is fixed in Graal 20.3.0 version which also is suggested in release notes
(https://www.graalvm.org/release-notes/20_3/#native-image) in the entry starting with
"Added support for method handles that represent a call to a single method accessible
by the Reflection API".
dmurat added a commit to croz-ltd/klokwrk-project that referenced this issue Jan 24, 2021
It turns out that GraalVM JDK 8 version (sdkman version: 20.3.0.r8-grl) works.
Previously I had a constraint because of oracle/graal#1306
Obviously it is fixed in Graal 20.3.0 version which also is suggested in release notes
(https://www.graalvm.org/release-notes/20_3/#native-image) in the entry starting with
"Added support for method handles that represent a call to a single method accessible
by the Reflection API".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants