Backport of b957ee40f302d54edf704b36120ef21fe977453a on top of vm-23.1.3
According to @eregon this is the fix that should be backported into GraalVM based on JDK21 to make use of Helidon+Graal.js possible.
Steps to reproduce the original problem as provided by @4e6:
$ git clone https://github.com/4e6/helidon-quickstart-se
$ cd helidon-quickstart-se
$ git checkout 00b472fc830f54a75e30884ebd153d74ea4c407d
$ JAVA_HOME=/graalvm-community-openjdk-21.0.2+13.1/ mvn -Pnative-image install -DskipTests
./target/helidon-quickstart-se
2024.08.17 16:21:40.664 Logging at runtime configured using classpath: /logging.properties
Exception in thread "main" java.lang.UnsupportedOperationException: Virtual threads are not supported together with Truffle JIT compilation.
at [email protected]/java.lang.Thread.ofVirtualWithoutLoom(Thread.java:674)
at [email protected]/java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor(Executors.java:269)
at io.helidon.webserver.LoomServer.<init>(LoomServer.java:74)
at io.helidon.webserver.WebServer.create(WebServer.java:45)
at io.helidon.webserver.WebServerConfig$Builder.build(WebServerConfig.java:662)
at io.helidon.examples.quickstart.se.Main.main(Main.java:43)
with here in provided fix I can build GraalVM as:
graal/vm$ mx --java-home ~/bin/labsjdk-ce-21.0.2-jvmci-23.1-b33/ --env ce --native-image=nic build
graal/vm$ mx --java-home ~/bin/labsjdk-ce-21.0.2-jvmci-23.1-b33/ --env ce --native-image=nic graalvm-home
/graal/sdk/mxbuild/linux-amd64/GRAALVM_350A482ABE_JAVA21/graalvm-350a482abe-java21-23.1.3
then I can replay the above steps with the newly built GraalVM at /graal/sdk/mxbuild/linux-amd64/GRAALVM_350A482ABE_JAVA21/graalvm-350a482abe-java21-23.1.3 and everything runs smoothly:
$ git clone https://github.com/4e6/helidon-quickstart-se
$ cd helidon-quickstart-se
$ git checkout 00b472fc830f54a75e30884ebd153d74ea4c407d
$ JAVA_HOME=/graal/sdk/mxbuild/linux-amd64/GRAALVM_350A482ABE_JAVA21/graalvm-350a482abe-java21-23.1.3 mvn -Pnative-image install -DskipTests
./target/helidon-quickstart-se
2024.08.17 16:25:10.047 Logging at runtime configured using classpath: /logging.properties
2024.08.17 16:25:10.065 Helidon SE 4.0.11 features: [Config, Encoding, Health, Media, Metrics, Observe, WebServer]
2024.08.17 16:25:10.065 [0x597ba75e] http://0.0.0.0:8080 bound for socket '@default'
2024.08.17 16:25:10.065 Started all channels in 0 milliseconds. 22 milliseconds since JVM startup. Java 21.0.2+13-jvmci-23.1-b33
WEB server is up! http://localhost:8080/simple-greet
Please consider my PR or your own backport b957ee40f302d54edf704b36120ef21fe977453a for backporting into release/graal-vm/23.1 branch. CCing @chumer.
@zakkak FYI. Probably something to discuss for https://github.com/graalvm/graalvm-community-jdk21u
FYI: @ola-lis has created an official ticket in My Oracle Support requesting fix for the Helidon 4 + Graal.js on native-image for JDK21 problem:
Is this the right way for an Oracle Java SE JDK and JRE licensee to request help from Oracle GraalVM team officially?
@JaroslavTulach we will have a look at your PR next week, August is vacation time.
If that is easy to backport, we can do it. You change seems quite big already; @peter-hofer will have a look and decide how easy and reasonable it is to merge that to our GraalVM-23.1. branch.
Tracked internally as GR-58288.
Thank you all for your feedback and explanations.
I should probably add that I have experimented with @Substitute annotation and I almost got my application running. I would succeed completely if I was able to override the existing substitution of Thread.ofVirtual to return null. But right now it is not possible to override existing substitution with another substitution. native-image complains about duplicated substitutions for the same method.
I am mentioning this for completeness. Obviously real support for my use-case would be better than hacking with @Substitutions.
We can add a way to disable existing substitutions via an option, and backport that option to the LTS versions
How would returning null from ofVirtual help you?
I suppose what you would be doing is to use the option to disable several substituting methods (e.g. -H:DisableSubstitutions=com.oracle.svm.core.thread.Target_java_lang_Thread.ofVirtualWithoutLoom) and introduce new substitutions that provide the behavior that you want.
I suppose what you would be doing is to use the option to disable several substituting methods (e.g.
-H:DisableSubstitutions=com.oracle.svm.core.thread.Target_java_lang_Thread.ofVirtualWithoutLoom) and introduce new substitutions that provide the behavior that you want.
Yes, -H:DisableSubstitutions=com.oracle.svm.core.thread.Target_java_lang_Thread.ofVirtualWithoutLoom and my own substitutions would be ideal!
How would returning
nullfromofVirtualhelp you?
Helidon is using Executors.newThreadPerTaskExecutor(Thread.ofVirtual());. I already have substitution for newThreadPerTaskExecutor - I just need ofVirtual() to not crash. But that's irrelevant. With -H:DisableSubstitutions=... we should be able to do it properly.
Thank you for helping Enso.
Helidon team has released version 4.1.2 which contains a fix and allows us to simply apply few substitutions and get our application working in native image: https://github.com/enso-org/enso/pull/10783#issuecomment-2396053536