Polyglot Java Application – only embedded polyglot snippets
If the Polyglot Java Application that we want to turn into a native image only used embedded, inline snippets of polyglot code, we can use a straightforward approach. We have to instruct the Native Image generator to include the respective runtimes for each of the languages we want to evaluate snippets of at run time – and the generator will comply. When the binary executable is executed, it has everything it needs to interpret the snippets of ‘polyglot’ code.
For example this application:
Our instruction to the GraalVM Native Image producer contains references to each of these languages:
<br> $GRAALVM_HOME/bin/native-image -cp ./application-bundle.jar --language:js --language:python --language:R --verbose -H:Name=myPolyglotApplication&nbsp; -H:Class=nl.amis.AppStarter<br>
Note: parameter -H:Name specifies the name of the native image. -H:Class indicates the Java Class whose main method is the entry point to the application. This means that when we run the binary executable, we trigger the native code equivalent of what was in that main method.
Note 2: at first, my native image generation failed with this error: Error: Image build request failed with exit status -1. I believe shortage of memory was the cause here. Producing a native image is quite memory intensive, especially when polyglot is added. I increased the memory size of my VM from 9GB to 16GB – and that helped me get rid of the error.
This application can now be run just like any other executable Linux application: ./myPolyglotApplication
When we invoke the executable, we are not aware of the fact that it was originally created from multiple programming languages and leverages multiple runtime engines.
Producing a Native Image for a Polyglot Java that loads Polyglot Resources from External Files
Unfortunately, this is not good enough for the Native Image. Once the native image is produced, the JAR file is irrelevant. The Native Image generator also does not somehow read all resources from the JAR and embeds these in the native image. What are my options? Well, I guess that I either can manually embed the contents of the validatorbundled.js file in a Java Class to ensure that the string content of the file is part of the Java code that makes it into the binary executable. This would work. And I can perhaps even make this into an automated step into my build pipeline.
Much more elegant is the approach that leverages ‘image build time class initialization”. Java Classes can contain a static initializer – code to be executed at Class load time instead of Object creation time (per Class instance). GraalVM Native Image can be instructed to initialize classes when creating the native image, to avoid running the same initialization code over and over again at every application start up. Objects created during image build time are available at run time – stored in the so-called image heap. Note that the GraalVM Feature API provides more fine grained control.
$GRAALVM_HOME/bin/native-image -cp ./application-bundle.jar <br>--language:js -H:Name=postalCodeValidator<br>-H:Class=nl.amis.java2js.ValidateThroughNPMValidator <br>--initialize-at-build-time=nl.amis.java2js.ValidateThroughNPMValidator <p>-H:+ReportUnsupportedElementsAtRuntime --allow-incomplete-classpath
The Java Class with the static initializer is coded as follows:
Keeping the external resources external – loading resources from the native image at runtime
The Java Class is coded as follows:
The command passed to GraalVM native image generation is:
$GRAALVM_HOME/bin/native-image -cp ./application-bundle.jar --language:js -H:Name=postalCodeValidator -H:Class=nl.amis.java2js.ValidateThroughNPMValidator --verbose -H:+ReportUnsupportedElementsAtRuntime --allow-incomplete-classpath
As an aside: on my non-optimized system, the startup time difference between the traditional JIT execution style and the native image is quite staggering: 0.08 vs 4.99 seconds:
GitHub Repository with sources for this article: https://github.com/AMIS-Services/jfall2019-graalvm
Medium article on class initialization at GraalVM Image Build Time: https://medium.com/graalvm/updates-on-class-initialization-in-graalvm-native-image-generation-c61faca461f7
GraalVM Docs on Native Image generation: https://www.graalvm.org/docs/reference-manual/native-image/
Intro to GraalVM on Ben’s Corner: https://fedidat.com/510-intro-to-graal/
JavaDocs for GraalVM Polyglot – https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/package-summary.html
GraalVM Docs – Polyglot – https://www.graalvm.org/docs/reference-manual/polyglot/