Building and running a GraalVM native image#
This example shows how to compile Java source code into a native image (executable that does not require the JVM) using GraalVM.
Note that some platform-specific prerequisites must be installed for this to work; see the GraalVM documentation for details.
import cjdk
import subprocess
java_source = """
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
"""
with open("Hello.java", "w") as fp:
fp.write(java_source)
Now let’s compile the source, first with javac to byte code, then to a native
image.
with cjdk.java_env(vendor="graalvm-community", version="25.0.1"):
subprocess.run(["javac", "Hello.java"], check=True)
subprocess.run(["native-image", "Hello"], check=True)
cjdk: Installing JDK graalvm-community:25.0.1 to /home/runner/.cache/cjdk
========================================================================================================================
GraalVM Native Image: Generating 'hello' (executable)...
========================================================================================================================
For detailed information and explanations on the build output, visit:
https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/BuildOutput.md
------------------------------------------------------------------------------------------------------------------------
[1/8] Initializing... (5.1s @ 0.12GB)
Java version: 25.0.1+8, vendor version: GraalVM CE 25.0.1+8.1
Graal compiler: optimization level: 2, target machine: x86-64-v3
C compiler: gcc (linux, x86_64, 13.3.0)
Garbage collector: Serial GC (max heap size: 80% of RAM)
1 user-specific feature(s):
- com.oracle.svm.thirdparty.gson.GsonFeature
------------------------------------------------------------------------------------------------------------------------
Build resources:
- 12.67GB of memory (75.6% of system memory, $CI set to 'true')
- 4 thread(s) (100.0% of 4 available processor(s), determined at start)
[2/8] Performing analysis... [******] (17.9s @ 0.37GB)
3,262 types, 3,721 fields, and 15,131 methods found reachable
1,056 types, 36 fields, and 415 methods registered for reflection
58 types, 59 fields, and 52 methods registered for JNI access
0 downcalls and 0 upcalls registered for foreign access
4 native libraries: dl, pthread, rt, z
[3/8] Building universe... (2.4s @ 0.42GB)
[4/8] Parsing methods... [*] (1.8s @ 0.44GB)
[5/8] Inlining methods... [****] (1.9s @ 0.47GB)
[6/8] Compiling methods... [****] (19.2s @ 0.41GB)
[7/8] Laying out methods... [*] (1.4s @ 0.50GB)
[8/8] Creating image... [*] (1.7s @ 0.55GB)
5.17MB (35.34%) for code area: 8,661 compilation units
7.67MB (52.37%) for image heap: 88,461 objects and 55 resources
1.80MB (12.29%) for other data
14.64MB in total image size, 13.76MB in total file size
------------------------------------------------------------------------------------------------------------------------
Top 10 origins of code area: Top 10 object types in image heap:
3.73MB java.base 1.39MB byte[] for code metadata
902.15kB svm.jar (Native Image) 1.19MB byte[] for java.lang.String
110.59kB java.logging 828.48kB java.lang.String
90.79kB org.graalvm.nativeimage.base 626.30kB com.oracle.svm.core.hub.DynamicHubCompanion
48.90kB jdk.proxy2 545.74kB heap alignment
38.97kB jdk.proxy1 460.10kB byte[] for general heap data
38.09kB org.graalvm.nativeimage.configure 424.96kB java.lang.Class
28.00kB jdk.internal.vm.ci 314.88kB java.util.HashMap$Node
25.44kB jdk.graal.compiler 221.12kB java.lang.Object[]
20.07kB org.graalvm.collections 178.74kB java.util.HashMap$Node[]
13.88kB for 5 more packages 1.48MB for 958 more object types
------------------------------------------------------------------------------------------------------------------------
Recommendations:
FUTR: Use '--future-defaults=all' to prepare for future releases.
HEAP: Set max heap for improved and more predictable memory usage.
CPU: Enable more CPU features with '-march=native' for improved performance.
------------------------------------------------------------------------------------------------------------------------
2.1s (3.9% of total time) in 491 GCs | Peak RSS: 1.14GB | CPU load: 3.62
------------------------------------------------------------------------------------------------------------------------
Build artifacts:
/tmp/tmp99w44qf8/hello (executable)
========================================================================================================================
Finished generating 'hello' in 52.6s.
Finally, let’s run the native image. Being a native image, it does not need
java_env() to run:
r = subprocess.run(["./hello"], check=True)
Hello, World!
r.returncode
0