Skip to content

Latest commit

 

History

History

examples

GraalVM code examples

GraalVM logo Directory examples\ contains GraalVM code examples coming from various websites - mostly from the GraalVM project and tested on a Windows machine.

In this document we present the following code examples in more detail:

ClassInitialization Example

Project ClassInitialization\ consists of the two classes HelloStartupTime.java and HelloCachedTime.java.

🔎 The example comes from Christian Wimmer's article "Updates on Class Initialization in GraalVM Native Image Generation", published on September 12, 2019.

Command build.bat with no argument displays the help message with the available options and subcommands (same result as build help):

> build
Usage: build { <option> | <subcommand> }
 
  Options:
    -cached     select main class with cached startup time
    -debug      print commands executed by this script
    -jvmci      add JVMCI options
    -native     generate both JVM files and native image
    -timer      print total execution time
    -verbose    print progress messages
 
  Subcommands:
    clean       delete generated files
    compile     generate executable
    doc         generate HTML documentation
    help        print this help message
    lint        analyze Java source files with CheckStyle
    run         run the generated executable
    test        execute JMH benchmarks

Command build.bat clean run produces the following output:

> build clean run
Startup: Fri Nov 15 22:43:31 CET 2019
Now:     Fri Nov 15 22:43:31 CET 2019

Command build.bat -verbose clean run also displays progress messages:

> build -verbose clean run
Delete directory target
Compile 2 Java source files to directory "target\classes"
Execute Java main class org.graalvm.example.HelloStartupTime
Copy resource files to directory "target\classes"
Execute Java main class org.graalvm.example.HelloStartupTime
Startup: Fri Nov 15 22:43:48 CET 2019
Now:     Fri Nov 15 22:43:48 CET 2019

Command build -native clean compile generates the native image target\HelloStartupTime.exe for source file HelloStartupTime.java :

> build -native clean compile
> tree /a /f target | findstr /v "^[A-Z]"
|   HelloStartupTime.exe
|   HelloStartupTime.exp
|   HelloStartupTime.lib
|   HelloStartupTime.obj
|   HelloStartupTime.pdb
|   HelloStartupTime.tmp
|   source_list.txt
|
\---classes
    \---org
        \---graalvm
            \---example
                    HelloStartupTime.class
                    Startup.class
 
> target\HelloStartupTime.exe
Startup: Fri Nov 15 22:50:01 CET 2019
Now:     Fri Nov 15 22:50:01 CET 2019

Command build.bat -native -cached clean compile generates the native image target\HelloCachedTime.exe for source file HelloCachedTime.java:

> build -native -cached clean compile
> tree /a /f target | findstr /v "^[A-Z]"
|   HelloCachedTime.exe
|   HelloCachedTime.exp
|   HelloCachedTime.lib
|   HelloCachedTime.obj
|   HelloCachedTime.pdb
|   HelloCachedTime.tmp
|   source_list.txt
|
\---classes
    \---org
        \---graalvm
            \---example
                    HelloCachedTime.class
                    Startup.class
 
> target\HelloCachedTime.exe
Startup: Fri Nov 15 22:53:31 CET 2019
Now:     Fri Nov 15 22:53:31 CET 2019

Command build -native -debug compile shows the the settings of commands javac.exe and native-image.cmd during the generation of executable target\HelloStartupTime.exe:

> build -native -debug compile
[build] Options    : _CACHED=0 _TARGET=native _TIMER=0 _VERBOSE=0
[build] Subcommands: _CLEAN=0 _COMPILE=1 _DOC=0 _LINT=0 _PACK=0 _RUN=0 _TEST=0
[build] Variables  : "GRAALVM_HOME=C:\opt\jdk-graalvm-ce-17.0.9_9.1"
[build] Variables  : "JAVA_HOME=C:\opt\jdk-graalvm-ce-17.0.9_9.1"
[build] Variables  : "MSVS_HOME=X:"
[build] Variables  : _MAIN_CLASS=org.graalvm.example.HelloStartupTime
[build] 00000000000000 Target : 'G:\examples\ClassInitialization\target\classes\.latest-build'
[build] 20191115223804 Sources: 'G:\examples\ClassInitialization\src\main\java\*.java'
[build] _COMPILE_REQUIRED=1
[build] "C:\opt\jdk-graalvm-ce-17.0.9_9.1\bin\javac.exe" "@G:\examples\ClassInitialization\target\javac_opts.txt" "@G:\examples\ClassInitialization\target\javac_sources.txt"
[build] "X:\VC\Auxiliary\Build\vcvarsall.bat" x64
**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.0
** Copyright (c) 2021 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
[build] INCLUDE="X:\\VC\Tools\MSVC\14.28.29910\ATLMFC\include;..."
[build] LIB="X:\\VC\Tools\MSVC\14.28.29910\ATLMFC\lib\x64;..."
[build] LIBPATH="X:\\VC\Tools\MSVC\14.28.29910\ATLMFC\lib\x64;..."
[build] "C:\opt\graalvm-ce-java11-22.3.2\bin\native-image.cmd" --trace-class-initialization --initialize-at-build-time=org.graalvm.example --initialize-at-run-time=org.graalvm.example.Startup -cp G:\examples\ClassInitialization\target\classes org.graalvm.example.HelloStartupTime G:\examples\ClassInitialization\target\HelloStartupTime
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]    classlist:   1,423.32 ms,  1.16 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]        (cap):   7,889.67 ms,  1.16 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]        setup:   9,858.53 ms,  1.16 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]     (clinit):     153.50 ms,  1.49 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]   (typeflow):   4,169.94 ms,  1.49 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]    (objects):   3,461.33 ms,  1.49 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]   (features):     220.37 ms,  1.49 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]     analysis:   8,152.19 ms,  1.49 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]     universe:     415.99 ms,  1.57 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]      (parse):     766.40 ms,  1.57 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]     (inline):     898.37 ms,  1.58 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]    (compile):   5,273.11 ms,  1.82 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]      compile:   7,280.26 ms,  1.82 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]        image:     630.74 ms,  1.82 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]        write:   1,235.45 ms,  1.82 GB
[G:\examples\ClassInitialization\target\HelloStartupTime:12076]      [total]:  29,404.27 ms,  1.82 GB
[build] _EXITCODE=0

CountUppercase Example

Project CountUppercase\ is a micro-benchmark:

  • system property iterations defines how many times the counting test is performed.
  • program arguments are concatenated into a sentence which is used as test input.

Command build.bat with no argument displays the help message with the available options and subcommands (same result as build help):

> build
Usage: build { <option> | <subcommand> }
 
  Options:
    -debug      print commands executed by this script
    -jvmci      add JVMCI options
    -native     generate both JVM files and native image
    -timer      print total execution time
    -verbose    print progress messages
 
  Subcommands:
    clean       delete generated files
    compile     generate executable
    doc         generate HTML documentation
    help        print this help message
    lint        analyze Java source files with CheckStyle
    run         run executable

Command build.bat clean run produces the following output (system property iterations=5 by default):

> build clean run
-- iteration 1 --
1 (375 ms)
2 (187 ms)
3 (141 ms)
4 (172 ms)
5 (140 ms)
6 (141 ms)
7 (187 ms)
8 (141 ms)
9 (141 ms)
total: 69999993 (1750 ms)
[...]
-- iteration 5 --
1 (125 ms)
2 (188 ms)
3 (125 ms)
4 (140 ms)
5 (141 ms)
6 (125 ms)
7 (140 ms)
8 (125 ms)
9 (141 ms)
total: 69999993 (1375 ms)

🔎 Executing the above command with option -debug also displays operations performed internally. The interesting parts are prefixed with label [build] (e.g. -Diterations=5):

> build run -debug | findstr /b "[debug]"
[build] Properties : _PROJECT_NAME=CountUppercase _PROJECT_VERSION=1.0-SNAPSHOT
[build] Options    : _TIMER=0 _VERBOSE=0
[build] Subcommands:  clean compile_jvm run_jvm
[build] Variables  : "GRAALVM_HOME=C:\opt\jdk-graalvm-ce-17.0.9_9.1"
[build] Variables  : "JAVA_HOME=C:\opt\jdk-graalvm-ce-17.0.9_9.1"
[...]
[build] C:\opt\jdk-graalvm-ce-17.0.9_9.1\bin\javac.exe -d G:\examples\CountUppercase\target\classes @G:\examples\CountUppercase\target\source_list.txt
[build] C:\opt\jdk-graalvm-ce-17.0.9_9.1\bin\java.exe -cp G:\examples\CountUppercase\target\classes -Diterations=5 -Dgraal.ShowConfiguration=info -Dgraal.PrintCompilation=true -Dgraal.LogFile=G:\examples\CountUppercase\target\graal_log.txt CountUppercase In 2019 I would like to run ALL languages in one VM.
[build] Compilation log written to G:\examples\CountUppercase\target\graal_log.txt
[build] _EXITCODE=0

Command build.bat -verbose lint analyzes the source files with our custom CheckStyle configuration 1:

> build -verbose lint
Analyze 1 Java source file with CheckStyle configuration "%LOCALAPPDATA%\Checkstyle\graal_checks.xml"
Starting audit...
Audit done.

🔎 Directory %LOCALAPPDATA%\Checkstyle contains both the CheckStyle configuration file graal_checks.xml and the CheckStyle library checkstyle-*-all.jar :

> dir /b %USERPROFILE%\.graal
checkstyle-10.2-all.jar
graal_checks.xml
 
> more %USERPROFILE%\.checkstyle\graal_checks.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
         "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
         "https://checkstyle.org/dtds/configuration_1_3.dtd">
 
<module name="Checker">
    <property name="localeCountry" value="US"/>
    <property name="localeLanguage" value="en"/>
    <property name="severity" value="error"/>
    ...
    <module name="TreeWalker">
    ...
    </module>
</module>

NiceMessage Example

Example NiceMessage illustrates how dynamic class loading is handled by the native-image tool when generating the native variant of a Java application.

🔎 The example comes from Vega's blog post "Building native images in Java with GraalVM", published on February 3, 2023.

Command build.bat clean run builds and executes the JVM variant of the Java application (target\Application.jar):

> build -verbose clean run
Delete directory "target"
Compile 4 Java source files to directory "target\classes"
Copy resource files to directory "target\classes"
Execute Java main class "dev.danvega.Application" MeanMessage
This is a mean message!

🔎 Passing the special GraalVM option -agentlib:native-image-agent=... when running the JVM application generates useful metadata information; in particular the file META-INF\native-image\reflect-config.json will be needed when generating the native application.

> tree /a /f target\META-INF |findstr /v "^[A-Z]"
\---native-image
    |   jni-config.json
    |   predefined-classes-config.json
    |   proxy-config.json
    |   reflect-config.json
    |   resource-config.json
    |   serialization-config.json
    |
    \---agent-extracted-predefined-classes

Command build.bat -native clean run builds and executes the native variant of the Java application (target\Application.exe):

🔎 The configuration file META-INF\native-image\reflect-config.json enumerates the two class variants which may be dynamically loaded in Application.java.

[
{
  "name":"dev.danvega.MeanMessage",
  "methods":[
    {"name":"","parameterTypes":[] }, 
    {"name":"printMessage","parameterTypes":[] }
  ]
},
{
  "name":"dev.danvega.NiceMessage",
  "methods":[
    {"name":"","parameterTypes":[] }, 
    {"name":"printMessage","parameterTypes":[] }
  ]
}
]
> build -verbose -native run
No action required ('src\main\java\*.java','src\main\resources\*')
No action required ('target\classes\*')
This is a mean message!

> target\Application.exe NiceMessage
This is a nice message!

> target\Application.exe MeanMessage
This is a mean message!

Ranking Example

Project Ranking\ is a micro-benchmark.

🔎 The example comes from Berger's article "An introduction to GraalVM", published on June 28, 2019.

Command build.bat with no argument displays the help message with the available options and subcommands (same result as build help):

> build
Usage: build { <option> | <subcommand> }
 
  Options:
    -debug      print commands executed by this script
    -jvmci      add JVMCI options
    -native     generate both JVM files and native image
    -timer      print total execution time
    -verbose    print progress messages
 
  Subcommands:
    clean       delete generated files
    compile     generate executable
    doc         generate HTML documentation
    help        print this help message
    lint        analyze Java source files with CheckStyle
    test        execute micro benchmark

Command build.bat clean run builds and executes the JVM variant of the JMH benchmark (target\benchmarks.jar):

> build -verbose clean run
Delete directory "target"
Compile 2 Java source files to directory "target\classes"
Create Java archive "target\benchmarks.jar"
Copy chart file to directory "target"
Execute JMH benchmark (JVM)
# JMH version: 1.35
# VM version: JDK 11.0.16, OpenJDK 64-Bit Server VM, 11.0.16+8-jvmci-22.2-b06
# VM invoker: C:\opt\graalvm-ce-java11-22.3.2\jre\bin\java.exe
# VM options: -XX:ThreadPriorityPolicy=1 [...] -Xmx1G
# Warmup: 3 iterations, 10 s each
# Measurement: 3 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: nl.avisi.Ranking.rank

# Run progress: 0.00% complete, ETA 00:01:00
# Fork: 1 of 1
# Warmup Iteration   1: files=[G:\examples\Ranking\target\chart2000-songyear-0-3-0058.csv]
13.601 ms/op
# Warmup Iteration   2: 11.303 ms/op
# Warmup Iteration   3: 11.644 ms/op
Iteration   1: 11.605 ms/op
Iteration   2: 11.700 ms/op
Iteration   3: 11.817 ms/op


Result "nl.avisi.Ranking.rank":
  11.707 ±(99.9%) 1.934 ms/op [Average]
  (min, avg, max) = (11.605, 11.707, 11.817), stdev = 0.106
  CI (99.9%): [9.773, 13.641] (assumes normal distribution)


# Run complete. Total time: 00:01:00
...
Benchmark     Mode  Cnt   Score   Error  Units
Ranking.rank  avgt    3  11.707 ± 1.934  ms/op

Command build.bat -verbose -native clean run builds and executes the native variant of the JMH benchmark (target\Ranking.exe):

> build -verbose -native clean run
Delete directory "target"
Compile 2 Java source files to directory "target\classes"
Create Java archive "target\benchmarks.jar"
Create native image "target\Ranking"
===============================================================================================
GraalVM Native Image: Generating 'G:\examples\Ranking\target\Ranking' (executable)...
===============================================================================================
[1/7] Initializing...                                                           (15,5s @ 0,21GB)
 Version info: 'GraalVM 22.3.2 Java 11 CE'
 C compiler: cl.exe (microsoft, x64, 19.29.30141)
 Garbage collector: Serial GC
[2/7] Performing analysis...  [*********]                                       (16,5s @ 1,59GB)
   3 828 (80,78%) of  4 739 classes reachable
   5 169 (50,96%) of 10 143 fields reachable
  17 994 (51,95%) of 34 640 methods reachable
     155 classes,     0 fields, and   527 methods registered for reflection
      71 classes,    57 fields, and    59 methods registered for JNI access
[3/7] Building universe...                                                       (1,4s @ 1,85GB)
[4/7] Parsing methods...      [*]                                                (1,2s @ 0,79GB)
[5/7] Inlining methods...     [****]                                             (1,3s @ 1,84GB)
[6/7] Compiling methods...    [****]                                            (13,1s @ 1,52GB)
[7/7] Creating image...                                                          (3,8s @ 1,88GB)
   6,98MB (41,72%) for code area:   10 718 compilation units
   8,53MB (50,99%) for image heap:   2 396 classes and 110 351 objects
   1,22MB ( 7,28%) for other data
  16,73MB in total
------------------------------------------------------------------------------------------------
Top 10 packages in code area:               Top 10 object types in image heap:
 717,91KB java.util                           1,42MB byte[] for code metadata
 421,83KB com.sun.crypto.provider             1,08MB byte[] for general heap data
 398,16KB com.oracle.svm.jni                  1,03MB java.lang.String
 378,81KB java.lang                         846,91KB java.lang.Class
 308,90KB java.io                           697,47KB byte[] for java.lang.String
 261,61KB java.util.concurrent              342,33KB java.util.HashMap$Node
 226,13KB java.util.regex                   328,97KB com.oracle.svm.core.hub.DynamicHubCompanion
 224,21KB java.text                         204,16KB java.lang.String[]
 220,99KB org.openjdk.jmh.runner            198,84KB java.util.concurrent.ConcurrentHashMap$Node
 211,82KB com.oracle.svm.core.reflect       168,16KB java.util.HashMap$Node[]
      ... 148 additional packages                ... 889 additional object types
                                           (use GraalVM Dashboard to see all)
------------------------------------------------------------------------------------------------
                        2,7s (4,8% of total time) in 19 GCs | Peak RSS: 4,12GB | CPU load: 4,83
------------------------------------------------------------------------------------------------
Produced artifacts:
 G:\examples\Ranking\target\Ranking.exe (executable)
 G:\examples\Ranking\target\sunmscapi.dll (jdk_lib)
 G:\examples\Ranking\target\Ranking.build_artifacts.txt
================================================================================================
Finished generating 'G:\examples\Ranking\target\Ranking' in 54,9s.
Execute JMH benchmark "target\Ranking.exe"
Exception in thread "main" java.lang.ExceptionInInitializerError
        at org.openjdk.jmh.runner.options.CommandLineOptions.<init>(CommandLineOptions.java:99)
        at org.openjdk.jmh.Main.main(Main.java:41)
Caused by: java.lang.IllegalArgumentException: int is not a value type
        at joptsimple.internal.Reflection.findConverter(Reflection.java:66)
        at org.openjdk.jmh.runner.options.IntegerValueConverter.<clinit>(IntegerValueConverter.java:35)
        ... 2 more

Footnotes

[1] CheckStyle configuration

The CheckStyle tool is available as a Java archive file checkstyle-*-all.jar which contains two example configuration files:
Note that the full CheckStyle distribution (aka "checkstyle-all") is not available from Maven Central and must be retrieved separately.

mics/May 2024