After upgrading to GraalVM 20.2.0 I noticed issues with native-image which seem to be coming from ZIO. A simple hello world like this can reproduce it:
object Main extends zio.App {
def run(args: List[String]): URIO[ZEnv, ExitCode] = {
putStrLn("hello").exitCode
}
}
I'm using sbt-native-packager for building the image and the settings are:
graalVMNativeImageOptions ++= Seq(
"-H:+ReportExceptionStackTraces",
"-H:+TraceClassInitialization",
"--initialize-at-build-time",
"--no-fallback"
)
This causes the following:
[error] Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call or single field access. The method handle must be a compile time constant, e.g., be loaded from a `static final` field. Method that contains the method handle invocation: java.lang.invoke.LambdaForm$MH/1864049056.invoke_MT(Object, Object)
[error] To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The error is then reported at run time when the invoke is executed.
[error] Detailed message:
[error] Trace:
[error] at parsing scala.runtime.Statics.releaseFence(Statics.java:148)
[error] Call path from entry point to scala.runtime.Statics.releaseFence():
[error] at scala.runtime.Statics.releaseFence(Statics.java:148)
[error] at scala.collection.immutable.$colon$colon.<init>(List.scala:623)
[error] at zio.Cause$Internal$.flatten(Cause.scala:885)
[error] at zio.Cause$Internal$.zio$Cause$Internal$$hashCode(Cause.scala:860)
[error] at zio.Cause$Internal$Both.hashCode(Cause.scala:819)
[error] at java.util.HashMap.hash(HashMap.java:339)
[error] at java.util.HashMap.get(HashMap.java:552)
[error] at com.oracle.svm.jni.access.JNIReflectionDictionary.getClassObjectByName(JNIReflectionDictionary.java:129)
[error] at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:324)
[error] at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_FindClass_3ec1032c6cb9443725d1e68194130533bfb04076(generated:0)
[error] com.oracle.svm.core.util.UserError$UserException: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call or single field access. The method handle must be a compile time constant, e.g., be loaded from a `static final` field. Method that contains the method handle invocation: java.lang.invoke.LambdaForm$MH/1864049056.invoke_MT(Object, Object)
...
If you also add the following unsafe options (generally not recommended), you can generate an executable, but running it will cause it to hang at startup with 100% CPU usage.
"--allow-incomplete-classpath",
"--report-unsupported-elements-at-runtime"
All this worked fine with GraalVM 20.1.0 and I've been successfully using it for a while in production. I think the cause might be how GraalVM 20.2.0 changed the initialization strategy a bit. I'm not entirely sure. It needs to be investigated.
If Graal native-image support is considered important for ZIO, maybe adding a verification step in CI could provide some value too.
The timing of sbt-native-image being released was good. 馃檪 Apparently the issue could be due to this:
https://github.com/scala/bug/issues/11634
I'm not sure why I'm not seeing it with GraalVM 20.1.0 though.
I'll give that workaround a try and report back.
Thanks for raising and for looking into this! Supporting Graal is definitely something we want to do!
I can confirm "org.scalameta" %% "svm-subs" % graalVersion fixes the issue I was seeing. Since this isn't an issue with ZIO itself, I think it's fine to close the issue. But it's something to be aware of if it comes up in the future.
Most helpful comment
The timing of sbt-native-image being released was good. 馃檪 Apparently the issue could be due to this:
https://github.com/scala/bug/issues/11634
I'm not sure why I'm not seeing it with GraalVM 20.1.0 though.
I'll give that workaround a try and report back.