1. GRAALVM
Three languages for the Elven fullstack developers under the sky,
Seven for the Dwarf backend developers in their halls of stone,
(*) Nine for the Mortal frontend developers doomed to die,
One for the Compiler Lord on his AST throne
In the Land of Bytecodes where the programs lie.
One VM to rule them all,
One VM to find them,
One VM to bring them all,
And in Bytecodes bind them,
In the Land of Bytecodes where the programs lie.
(*) The languages are doomed to die, not the developers!
3. WHO AM I
JORGE HIDALGO
Senior Manager – Senior Technology Architect
Accenture Technology – Global Java Practice Lead
Advanced Technology Center in Spain – Open Engineering Lead
Málaga JUG Lead
Father of two, husband, whistle player, video gamer, sci-fi *.*, Lego,
Star Wars, Star Trek, Starcraft, Halo, Borderlands, Raspberry Pi, Arduino… LLAP!
4. TL;DR
Examples are adapted from Chris Seaton’s workshop in
Oracle Code One 2018
Thanks to Chris for allowing us to reuse them
All examples can be found here:
https://github.com/deors/workshop-graalvm
4
5. GRAALVM
GraalVM – https://graalvm.org/
• Brand new polyglot virtual machine by Oracle Labs
• JVM languages, and much more!
• Written in Java -- easier to hack and to evolve
• Faster, leaner, production-ready for certain use cases
• Two flavours:
• Open source (community edition)
• Enterprise edition with further enhancements
In this session we will show some of GraalVM use cases
5
6. GRAALVM
This is the high-level internal architecture of GraalVM
Java HotSpot VM
SubstrateVMJVM Compiler Interface
Graal Compiler
Truffle Framework
Sulong
6
7. GRAALVM
AGENDA
1. GraalVM as a drop-in replacement for JDK
2. Graal as a compiler in JDK
3. Java native images
4. Polyglot VM
5. Seamless language interop
6. VM for native languages
7. Common debugging interface
8. Common monitoring interface
9. Java programs as native libraries
7
9. GRAALVM
1. GraalVM as a drop-in replacement for JDK
• GraalVM can be used simply as an alternate VM
to run JVM programs
• 1.8 at the moment, with 11 coming soon
• It is a drop-in replacement, including all the expected tools
and the same familiar command line arguments
• New tools and commands for GraalVM specific features
9
10. GRAALVM
1. GraalVM as a drop-in replacement for JDK
• GraalVM has multiple components, being the Graal
compiler one of them, running on top of the HotSpot VM
thanks to the JVM Compiler Interface (JVMCI)
• Graal is written in Java, easier to maintain and to evolve
• In many cases, programs executed with Graal have better
performance and memory footprint out of the box
10
11. GRAALVM
1. GraalVM as a drop-in replacement for JDK
Image from Chris Thalinger’s talk on Joker 2017 conference –
“Twitter’s Quest for a Wholly Graal Runtime”
https://2017.jokerconf.com/en/2017/talks/3qdblcadmqy0me
2uuieqaq/
11
12. GRAALVM
1. GraalVM as a drop-in replacement for JDK
# add GraalVM to path
export PATH=~/code/tools/graalvm-ce-19.2.0.1/Contents/Home/bin:$PATH
# explore version info
java -version
12
13. GRAALVM
1. GraalVM as a drop-in replacement for JDK
# a simple test – program which counts words in a file
cd ~/graalvm/topten
javac TopTen.java
# running with Graal compiler (activated by default in GraalVM)
time java TopTen quick-brown-fox.txt
time java TopTen alice-in-wonderland.txt
time java TopTen war-and-peace.txt
# same program but with Graal compiler disabled
time java -XX:-UseJVMCICompiler TopTen war-and-peace.txt
13
14. GRAALVM
1. GraalVM as a drop-in replacement for JDK
• In a simple program, where code is executed only once or
a few times, performance improvement is small or null
• The JIT compiler in Graal, as happens with C1/C2, works
better with time, translating bytecodes into native code by
applying multiple optimizations which are fine-tuned as
execution progresses
• Using GraalVM in long running programs is the best way to
check whether Graal is improving performance or not
14
15. GRAALVM
1. GraalVM as a drop-in replacement for JDK
# another test, operating with complex numbers in large
cd ~/graalvm/value-types
mvn package
# running with Graal compiler (activated by default in GraalVM)
# this test uses JMH microbenchmarks
java -jar target/benchmarks.jar -prof gc
# same program but with Graal compiler disabled
java -XX:-UseJVMCICompiler -jar target/benchmarks.jar -prof gc
15
17. GRAALVM
2. Graal as a compiler in JDK
• Graal compiler is also included with OpenJDK 11+
• It is not the latest version, so its performance is not on par
with GraalVM yet, but will be updated in forthcoming
OpenJDK releases
• It can be used as an
alternate compiler to
C1/C2 activating it
with JVM flags
17
Java HotSpot VM
SubstrateVMJVM Compiler Interface
Graal Compiler
Truffle Framework
Sulong
18. GRAALVM
2. Graal as a compiler in JDK
# repeat the test which counts words on a file
# with OpenJDK 11+ standard compiler
cd ~/graalvm/topten
time java TopTen war-and-peace.txt
# with OpenJDK 11+ Graal compiler
time java -XX:+UnlockExperimentalVMOptions
-XX:+EnableJVMCI
-XX:+UseJVMCICompiler
TopTen war-and-peace.txt
Enables JVMCI and uses JVMCI compiler by
default in OpenJDK
It is not necessary to specify Graal, as it is
the only JVMCI-compliant compiler
available in the modulepath/classpath
18
19. GRAALVM
2. Graal as a compiler in JDK
# repeat the test which operates with complex numbers
# with OpenJDK 11+ standard compiler
cd ~/graalvm/value-types
java -jar target/benchmarks.jar -prof gc
# with OpenJDK 11+ Graal compiler
java -XX:+UnlockExperimentalVMOptions
-XX:+EnableJVMCI
-XX:+UseJVMCICompiler
-jar target/benchmarks.jar -prof gc
19
21. GRAALVM
3. Java native images… Yes! NATIVE JAVA!!
• JVM JIT (just in time) compiler optimisation while on
runtime has a ramp up curve and a larger resource
consumption which pays off on long running processes,
like batch, big data, scientific comp. and app servers
• But not very good for short lived processes, like CLI or
functions in the cloud-native world where startup time is a
major concern
21
22. GRAALVM
3. Java native images
• Graal can be used as an AOT (ahead of time) compiler to
create native images of JVM bytecodes…
• …But with some caveats:
• Reflection needs extra configuration
• Dynamic proxies need extra configuration
• No InvokeDynamic (except for lambdas)
• No bytecode generation
22
23. GRAALVM
3. Java native images
# native images are not installed by default with GraalVM
# SubstrateVM, which is the component that does the AOT magic
# must be installed first as an add-on
gu install native-image
Java HotSpot VM
SubstrateVMJVM Compiler Interface
Graal Compiler
Truffle Framework
Sulong
23
24. GRAALVM
3. Java native images
# run again a simple, short live program with GraalVM
cd ~/graalvm/topten
time java TopTen quick-brown-fox.txt
# create the native image with AOT compiler (no bytecodes were harmed!)
native-image TopTen
# run the native image
time ./topten quick-brown-fox.txt
# examine dependencies – self-contained, no GraalVM or OpenJDK in sight
otool -L topten
24
25. GRAALVM
3. Java native images
# a more complex scenario with reflection
cd ~/graalvm/reflection
mvn compile
# run the example bytecodes in GraalVM
java -cp target/classes graalvm.reflection.ReflectionExample
# create the native image
native-image -cp target/classes graalvm.reflection.ReflectionExample
# run the native image
./graalvm.reflection.ReflectionExample
25
26. GRAALVM
3. Java native images
# another example with reflection
# (class names configured in a properties file)
java -cp target/classes graalvm.reflection.ReflectionPropsExample
# create the native image
native-image -cp target/classes
graalvm.reflection.ReflectionPropsExample
# run the fallback native image (it stills need the JDK to work!)
./graalvm.reflection.ReflectionPropsExample
26
27. GRAALVM
3. Java native images
# use the tracing agent to record dynamic behaviour
mkdir target/native-image
java -agentlib:native-image-agent=config-output-dir=target/native-image
-cp target/classes graalvm.reflection.ReflectionPropsExample
# create the native image using the recorded traces
native-image -H:ReflectionConfigurationFiles=target/native-image/reflect-config.json
-H:ResourceConfigurationFiles=target/native-image/resource-config.json
-cp target/classes
graalvm.reflection.ReflectionPropsExample
# run the perfectly generated native image
./graalvm.reflection.ReflectionPropsExample
27
28. GRAALVM
3. Java native images
• GraalVM native images are excellent to build Docker
images for processes that require a fast startup time
• As native images have minimal dependencies and do not
need the JDK, the image size is very small
• To build the Docker image, the native executable has to be
generated within a container to ensure portability
28
30. GRAALVM
3. Java native images
# create the native image within the container
docker run -it --rm
--mount type=bind,source=$PWD,target=/opt/graalvm
graalvm-native-image
"--static"
"-H:ReflectionConfigurationFiles=target/native-image/reflect-config.json"
"-H:ResourceConfigurationFiles=target/native-image/resource-config.json"
"-cp" "target/classes"
"graalvm.reflection.ReflectionPropsExample"
# the executable is a Linux exec and may not work on your machine
./graalvm.reflection.reflectionpropsexample
30
31. GRAALVM
3. Java native images
# create the Docker image to run the program (Alpine Linux is enough)
docker build -t reflectionpropsexample
-f reflectionspropsexample.Dockerfile .
docker images | grep reflectionpropsexample
# run the native image within a container
docker run -it --rm reflectionpropsexample
31
32. GRAALVM
3. Java native images
• These huge performance improvements on startup time
represent a major milestone for the JVM ecosystem
• Paves the way for the “faster, leaner Java” movement:
• Micronaut
• Quarkus
• Spring (*)
• Serverless computing
32
(*) https://github.com/spring-projects/spring-framework/wiki/GraalVM-native-image-support
34. GRAALVM
4. Polyglot VM
• GraalVM, thanks to Truffle framework, provides support for
non-JVM languages
• JavaScript implementations, js and node, are
production-ready
• Other languages are
still experimental:
Ruby, Python and R
Java HotSpot VM
SubstrateVMJVM Compiler Interface
Graal Compiler
Truffle Framework
Sulong
34
35. GRAALVM
4. Polyglot VM
# GraalVM own implementation of JavaScript
js --version
# GraalVM own implementation of Node.js
node --version
# it also includes npm
npm --version
35
36. GRAALVM
4. Polyglot VM
# simple web app running with Node.js and Express
cd ~/graalvm/hello-express
npm install express
node hello-express.js
36
37. GRAALVM
4. Polyglot VM
# install experimental languages (not included by default)
gu install ruby && ruby --version
gu install python && graalpython --version
gu install R && R --version
# list enabled extensions
gu list
# rebuild polyglot native images (highly recommended)
gu rebuild-images polyglot libpolyglot js llvm python ruby
37
38. GRAALVM
4. Polyglot VM
# run a simple Ruby program with GraalVM
cd ~/graalvm/hello-ruby
ruby hello-ruby.rb
# run a simple Python program with GraalVM
cd ~/graalvm/hello-python
graalpython hello-python.py
38
40. GRAALVM
5. Seamless language interop
• Being polyglot is cool, but being able to bring seamless
interoperability across all supported languages is
awesome!
• Every language implementation is actually processing
bytecodes, optimizing them as the execution progresses,
in a common pipeline – same JIT compiler, same
underlying VM – so it’s feasible to make this happen
40
41. 5. Seamless language interop
# example of a Ruby program calling Java
cd ~/graalvm/interop
ruby --jvm ruby-java.rb
# example of a Python program calling Java
graalpython --jvm python-java.rb
GRAALVM
The --jvm flag enables the interop
with JVM languages
41
42. GRAALVM
5. Seamless language interop
# example of a Ruby program calling JavaScript
ruby --jvm --polyglot ruby-javascript.rb
To call other languages, the extra
--polyglot param is needed
42
43. GRAALVM
5. Seamless language interop
# example of a Node.js program calling R
cd ~/graalvm/cloudplot
npm install express
node --jvm --polyglot cloudplot.js
# renders in browser
http://localhost:8080
http://localhost:8080/js
43
45. GRAALVM
6. VM for native languages
• GraalVM also has an interpreter for LLVM, named Sulong
• With this interpreter Truffle translates into bytecodes any
language with a compiler capable of emitting LLVM codes
• C, C++, Rust
– maybe others, too
• Very experimental
– performance still far
from desirable
Java HotSpot VM
SubstrateVMJVM Compiler Interface
Graal Compiler
Truffle Framework
Sulong
45
46. GRAALVM
6. VM for native languages
# compile a C program in the normal way, and emitting LLVM
cd ~/graalvm/gzip
clang gzip.c -o gzip
clang -c -emit-llvm gzip.c
# execute the C native program
time ./gzip -d war-and-peace.txt.gz &&
time ./gzip war-and-peace.txt
# execute the program with Sulong (GraalVM LLVM bitcode interpreter)
time lli gzip.bc -d war-and-peace.txt.gz &&
time lli gzip.bc war-and-peace.txt
46
48. GRAALVM
7. Common debugging interface
• A consequence of running multiple languages in the same
compiler framework it to have a common debugging
interface
• Even for programs with language interop
• Extremely useful as not all languages have debuggers, or
have them but not so good as we are used with JVM
languages
48
49. GRAALVM
7. Common debugging interface
# debugging a Ruby program
cd ~/graalvm/fizzbuzz
ruby --inspect fizzbuzz.rb
# debugging a Python program
graalpython --inspect fizzbuzz.py
# debugging an R program
R --inspect -f fizzbuzz.r
# debugging a JavaScript program
js --inspect fizzbuzz.js
49
51. GRAALVM
8. Common monitoring interface
• In the JVM world we are used to tools like VisualVM or
Mission Control to monitor applications and connect with
JMX metrics and actions
• With GraalVM, it is possible to leverage all those tools in
any supported languages
• Command-line options to enable tracing are available, too
• Invaluable as not all languages have monitoring tools, or
they are far from what it is common in the JVM
51
52. GRAALVM
8. Common monitoring interface
# monitoring a Ruby program
cd ~/graalvm/infloop
ruby --jvm infloop.rb
# in a separate console
jvisualvm
52
54. GRAALVM
9. Java programs as native libraries
• GraalVM enables us to run programs in many languages
• We can interop across those languages
• We can convert to native image
• It is also possible to run Java programs from any native
program, or programs with foreign function interfaces (FF),
like Ruby, Python, Rust, Go, Haskell, Dart, etc.
54
55. GRAALVM
9. Java programs as native libraries
• Many advantages to Java (and others) developers:
• Interfaces are automatically generated
• Very simple API
• Library is automatically generated
• Access to the Java ecosystem from anywhere
• Like JNI... but much, much, much easier than JNI!
55
56. GRAALVM
9. Java programs as native libraries
# program which calculates distances with Apache SIS
cd ~/graalvm/distance
javac -cp sis.jar Distance.java
java -cp sis.jar:. Distance 51.507222 -0.1275 40.7127 -74.0059
# create native image
native-image -cp sis.jar:. Distance
./distance 51.507222 -0.1275 40.7127 -74.0059
56
58. GRAALVM
9. Java programs as native libraries
# creates a native library from the same program
native-image -cp sis.jar:. --shared -H:Name=libdistance Distance
# interfaces and library are automatically generated
ls -l libdistance*
# the Apache SIS Java library is now used from a C program
clang -I. -L. -ldistance distance.c -o distancec
otool -L distancec
./distancec 51.507222 -0.1275 40.7127 -74.0059
😍 58
60. CONCLUSIONS
GraalVM – https://graalvm.org/
• Freedom of choice of language
• Access to multiple ecosystems
• JVM or native images
• Full interop across languages
• Debugging and monitoring tools
• With better performance in many cases
• ‘ONE VM TO RULE THEM ALL’ J
60