DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • All You Need To Know About Garbage Collection in Java
  • Java’s Next Act: Native Speed for a Cloud-Native World
  • The Energy Efficiency of JVMs and the Role of GraalVM
  • Five Java Developer Must-Haves for Ultra-Fast Startup Solutions

Trending

  • Beyond Linguistics: Real-Time Domain Event Mapping with WebSocket and Spring Boot
  • Streamlining Event Data in Event-Driven Ansible
  • Is the Model Context Protocol a Replacement for HTTP?
  • Key Considerations in Cross-Model Migration
  1. DZone
  2. Coding
  3. Java
  4. Learning to Use the GraalVM

Learning to Use the GraalVM

The GraalVM is a handy virtual machine that supports multiple languages and enables native images for better performance.

By 
Mani Sarkar user avatar
Mani Sarkar
·
Feb. 07, 18 · Tutorial
Likes (15)
Comment
Save
Tweet
Share
43.4K Views

Join the DZone community and get the full member experience.

Join For Free

In the post "Truffle served in a Holy Graal: Graal and Truffle for polyglot language interpretation on the JVM," we got a brief introduction and a bit of deep dive into Graal, Truffle, and some of the concepts around it. But no technology is fun without diving deep into its practicality, otherwise it's like Theoretical Physics or Pure Maths — abstract for some, boring for others (sorry, the last part was just me ranting).

In this post, we will be taking a look into the GraalVM, by installing it, comparing SDK differences and looking at a some of the examples that illustrate how different languages can be compiled and run on the GraalVM, and also how they can be run in the same context and, finally, natively (more performant).

GraalVM is similar to any Java SDK (JDK) that we download from any vendor, except that it has JVMCI: Java-level JVM Compiler Interface support, and Graal is the default JIT compiler. It can not just execute Java code but also languages like JS, Ruby, Python, and R. It can also enable building ahead-of-time (AOT) compiled executables (native images) or share libraries for Java programs and other supported languages — although we won't be going through every language, only a select few of them.

Just to let you know, all of the commands and actions have been performed on an Ubuntu 16.04 operating system environment. They should work on MacOSX with minor adaptations, though on Windows, a more changes would be required.

Hands-On

We can get our hands on the GraalVM in more than one way, either building it on our own or downloading a pre-built version from a vendor website:

  • Build on our own: some cloning and other magic (we can see that later on)
  • Download a ready-made JVM: OTN download site
  • Hook up a custom JIT to an existing JDK with JVMCI support (we can that see later on)

As we are using a Linux environment, it would be best to download and install the Linux (preview) version of GraalVM based on JDK8 (> 500MB file, need to Accept the license, need to be signed in on OTN or you will be taken to https://login.oracle.com/mysso/signon.jsp).

Follow the installation information on the download page. After unpacking the archive, you will find a folder by the name of graalvm-0.30 (at the time of writing of this post) when you execute the command below:

$ tar -xvzf graalvm-0.30-linux-amd64-jdk8.tar.gz


Eagle Eyeing: Compare SDKs

We will quickly check the contents of the SDK to gain some familiarity with it, so let's check the contents of the GraalVM SDK folder:

$ cd graalvm-0.30
$ ls

Which looks familiar and has similarities when compared with the traditional Java SDK folder (i.e. JDK 1.8.0_44):

$ cd /usr/lib/jdk1.8.0_44
$ ls

Except we have quite a few additional artifacts to learn about, i.e. the launchers on the VM for the supported languages like FastR, JS (GraalJS), NodeJS (GraalNodeJS), Python, Ruby, and Sulong (C/C++, Fortran).

Comparing the folder between the GraalVM SDK and say JDK 1.8.0_44 SDK, we can see that we have a handful of additional files in there:

(Use tools like meld or just diff to compare directories.)

Similarly, we can see that the folder has interesting differences, although it's semantically similar to the traditional Java SDKs. A few items that look interesting in the list are Rscript, lli, and ployglot.

Now we haven't literally compared the two SDKs to mark elements that are different or missing in one or the other, but the above gives us an idea about what is offered and how to use the features it provides — well, this SDK has them baked into it the examples folder.

If the examples folder is NOT distributed in the future versions, please use the respective code snippets provided for each of the sections referred to (for each language).

For this post, you won't need the examples folder to be present.


$ tree -L 1 examples

(Use the tree command — sudo apt-get tree to see the above — available on MacOSX and Windows)

Each of the sub-folders contains examples for the respective languages supported by the GraalVM, including embed and native-image, which we will also be looking at.

Exciting Part: Hands-On Using the Examples

Let's cut to the chase. But before we can execute any code and see what the examples do, we should move graalvm-0.30 to where the other Java SDKs reside, let's say under /usr/lib/jvm/, and set an environment variable called GRAAL_HOME to point to it:

$ sudo mv -f graalvm-0.30 /usr/lib/jvm
$ export GRAAL_HOME=/usr/lib/jvm/graalvm-0.30
$ echo "export GRAAL_HOME=/usr/lib/jvm/graalvm-0.30" >> ~/.bashrc
$ cd examples


R Language

Let's pick R and run some R script files:

$ cd R
$ $GRAAL_HOME/bin/Rscript --help    #to see the usage text


Beware that we are running Rscript and not R, both can run R scripts — the latter is an R REPL.

Running hello_world.R using Rscript:

$ $GRAAL_HOME/bin/Rscript hello_world.R
[1] "Hello world!"


JavaScript

Next we try out some JavaScript:

$ cd ../js/
$ $GRAAL_HOME/bin/js --help         # to get to see the usage text


Running hello_world.js with js:

$ $GRAAL_HOME/bin/js hello_world.js
Hello world!


Embed

Now let's try something different — what if you wish to run code written in multiple languages, all residing in the same source file, on the JVM.

$ cd ../embed


We can do that using the org.graalvm.polyglot.context class. Here's a snippet of code from HelloPolyglotWorld.java:

import org.graalvm.polyglot.*;

public class HelloPolyglotWorld {

    public static void main(String[] args) throws Exception {
        System.out.println("Hello polyglot world Java!");
        Context context = Context.create();
        context.eval("js", "print('Hello polyglot world JavaScript!');");
        context.eval("ruby", "puts 'Hello polyglot world Ruby!'");
        context.eval("R", "print('Hello polyglot world R!');");
        context.eval("python", "print('Hello polyglot world Python!');");
    }
}


Compile it with the following command to get a .class file created:

$ $GRAAL_HOME/bin/javac HelloPolyglotWorld.java


And run it with the following command to see how that works:

$ $GRAAL_HOME/bin/java HelloPolyglotWorld
Hello polyglot world Java!
Hello polyglot world JavaScript!
Hello polyglot world Ruby!
[1] "Hello polyglot world R!"
Hello polyglot world Python!


You might have noticed a bit of sluggishness with the execution when switching between languages and printing the "Hello polyglot world...." messages. Hopefully, we will learn why this happens — and maybe even be able to fix it.

Native Image

The native image feature with the GraalVM SDK helps improve the startup time of Java applications and gives them a smaller footprint. Effectively, it's converting bytecode that runs on the JVM (on any platform) to native code for a specific OS/platform — which is where the performance comes from. It's using aggressive ahead-of-time (AOT) optimizations to achieve good performance.

Let's see how that works.

$ cd ../native-image


Let's take a snippet of Java code from HelloWorld.java in this folder:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}


Compile it into bytecode:

$ $GRAAL_HOME/bin/javac HelloWorld.java


Compile the bytecode (HelloWorld.class) into native code:

$ $GRAAL_HOME/bin/native-image HelloWorld
 classlist: 740.68 ms
 (cap): 1,042.00 ms
 setup: 1,748.77 ms
 (typeflow): 3,350.82 ms
 (objects): 1,258.85 ms
 (features): 0.99 ms
 analysis: 4,702.01 ms
 universe: 288.79 ms
 (parse): 741.91 ms
 (inline): 634.63 ms
 (compile): 6,155.80 ms
 compile: 7,847.51 ms
 image: 1,113.19 ms
 write: 241.73 ms
 [total]: 16,746.19 ms


Taking a look at the folder, we can see the Hello World source and the compiled artifacts:

3.8M -rwxrwxr-x 1 xxxxx xxxxx 3.8M Dec 12 15:48 helloworld
 12K -rw-rw-r-- 1 xxxxx xxxxx     427 Dec 12  15:47 HelloWorld.class
 12K -rw-rw-r-- 1 xxxxx xxxxx     127 Dec 12  13:59 HelloWorld.java


The first file, helloworld, is the native binary that runs on the platform we compiled it on using the native-image command, which can be directly executed with the help of the JVM:

$ helloworld
Hello, World!


Even though we gain performance, we might be losing out on other features that we get when running in bytecode form on the JVM — the choice of which route to take is all a matter of the use case and what is important for us.

That calls for a wrap up — it's quite a lot to read and try out on the command-line, but it's well worth the time to explore the interesting GraalVM.

To sum up, we went about downloading the GraalVM from Oracle Lab's website, unpacked it, had a look at the various folders, and compared it with our traditional looking Java SDKs. Then, we noticed and noted the differences.

We further looked at the examples provided for the various Graal-supported languages and picked up a handful of features, which gave us a taste of what the GraalVM can offer. While we can run our traditional Java applications on it, we now also have the opportunity to write applications expressed in multiple supported languages in the same source file or the same project. This also gives us the ability to do seamlessly interop between the different aspects of the application written in a different language. We also have the ability to re-compile our existing applications for native environments (native-image) for performance and a smaller footprint.

For more details on examples, please refer to http://www.graalvm.org/docs/examples/.

GraalVM Java (programming language) Software development kit application operating system IT Command (computing) Java virtual machine

Published at DZone with permission of Mani Sarkar. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • All You Need To Know About Garbage Collection in Java
  • Java’s Next Act: Native Speed for a Cloud-Native World
  • The Energy Efficiency of JVMs and the Role of GraalVM
  • Five Java Developer Must-Haves for Ultra-Fast Startup Solutions

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!