Native Images
JBang supports creating native images using GraalVM’s native-image tool, allowing you to compile your Java scripts into standalone native executables.
What are Native Images?
Native images are compiled, standalone executables that:
-
Start instantly (no JVM startup time)
-
Use less memory
-
Don’t require Java to be installed
-
Are platform-specific binaries
Perfect for CLI tools, serverless functions, and anywhere startup time matters.
Prerequisites for Native Image
Additional software development tools are required for native image compilation on Linux, MacOS and Windows:
Installing GraalVM and Native Image
You need GraalVM with native-image installed:
Installing GraalVM
Option 1: SDKMAN (Recommended)
sdk install java 25.0.1-graal
sdk use java 25.0.1-graal
Option 2: Manual Download
-
Download GraalVM from https://www.graalvm.org/downloads/
-
Unpack the archive to folder /path/to/<graalvm>
-
export
JAVA_HOME=/path/to/<graalvm> -
export
PATH=/path/to/<graalvm>/bin:$PATH
Option 3: Package Managers
# macOS with Homebrew (using Bash)
brew install --cask graalvm-jdk@25
export JAVA_HOME=$(/usr/libexec/java_home -v 25)
export PATH=$JAVA_HOME/bin:$PATH
# Linux distributions
# Follow GraalVM documentation for your distro
Creating Native Images
Basic Native Image
# Compile to native image and run it
jbang --native hello.java
The native executable will be created in the global JBang cache directory.
Native Image Options
Control native image compilation with //NATIVE_OPTIONS:
///usr/bin/env jbang "$0" "$@" ; exit $?
//NATIVE_OPTIONS -O2 --no-fallback --enable-preview
class FastApp {
public static void main(String[] args) {
System.out.println("Native app running!");
}
}
Or from command line:
jbang --native --native-option="-O2" --native-option="--no-fallback" app.java
Common Native Image Configurations
CLI Applications
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS info.picocli:picocli:4.6.3
//DEPS info.picocli:picocli-codegen:4.6.3
//NATIVE_OPTIONS --no-fallback -H:+ReportExceptionStackTraces
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
@Command(name = "greet", mixinStandardHelpOptions = true)
class GreetApp implements Runnable {
@Parameters(description = "Name to greet")
String name = "World";
public static void main(String[] args) {
new CommandLine(new GreetApp()).execute(args);
}
public void run() {
System.out.println("Hello " + name + "!");
}
}
|
PicoCLI Native Images: Always include
|
Reflection-Heavy Applications
///usr/bin/env jbang "$0" "$@" ; exit $?
//NATIVE_OPTIONS --no-fallback -H:+ReportExceptionStackTraces
//NATIVE_OPTIONS -H:ReflectionConfigurationFiles=reflection-config.json
// Your reflection-heavy code
JSON Processing
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.fasterxml.jackson.core:jackson-databind:2.15.2
//NATIVE_OPTIONS --no-fallback
//NATIVE_OPTIONS -H:+ReportExceptionStackTraces
import com.fasterxml.jackson.databind.ObjectMapper;
class JsonApp {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// Your JSON processing code
}
}
Exporting Native Binaries
Container-Based Native Images
Using Docker
Create a Dockerfile:
FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22.3.0 AS builder
RUN gu install native-image
COPY . /app
WORKDIR /app
RUN curl -Ls https://sh.jbang.dev | bash -s - app setup
RUN ~/.jbang/bin/jbang --native myapp.java
FROM scratch
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]
Build:
docker build -t myapp-native .
docker run --rm myapp-native arg1 arg2
Multi-Stage Builds
# Builder stage
FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22.3.0 AS builder
RUN gu install native-image
COPY . /workspace
WORKDIR /workspace
RUN curl -Ls https://sh.jbang.dev | bash -s - --native myapp.java
# Runtime stage
FROM debian:bullseye-slim
COPY --from=builder /workspace/myapp /usr/local/bin/myapp
ENTRYPOINT ["myapp"]
Performance Optimization
Troubleshooting Native Images
Common Issues
Problem: UnsupportedFeatureError during compilation
Solution: Add reflection configuration or use --no-fallback to see exact issue
Problem: Missing reflection configuration Solution: Use GraalVM tracing agent:
jbang --jvm=graalvm --runtime-option="-agentlib:native-image-agent=config-output-dir=config" myapp.java
jbang --native --native-option="-H:ConfigurationFileDirectories=config" myapp.java
Problem: Large binary size Solution: Use optimization flags:
//NATIVE_OPTIONS --no-fallback -O2 --gc=serial -H:+StaticExecutableWithDynamicLibC
Problem: Slow compilation Solution: Use parallel compilation:
//NATIVE_OPTIONS -H:+UnlockExperimentalVMOptions -H:+UseParallelGC
Framework-Specific Considerations
Spring Boot
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.springframework.boot:spring-boot-starter-web:3.1.0
//DEPS org.springframework.experimental:spring-native:0.12.1
//NATIVE_OPTIONS --no-fallback --enable-all-security-services
// Spring Boot native configuration
Best Practices
Development Workflow
-
Develop with JVM - faster iteration
-
Test regularly with native - catch issues early
-
Use reflection configuration - for complex apps
-
Profile and optimize - measure before optimizing
Performance Comparison
| Metric | JVM | Native Image |
|---|---|---|
Startup Time |
~500ms-2s |
~10-50ms |
Memory Usage |
High (heap + metaspace) |
Lower (no JVM overhead) |
Peak Performance |
Higher (JIT optimization) |
Consistent but lower |
Binary Size |
Small JAR + JVM |
Larger standalone binary |
Build Time |
Fast |
Slower (1-10 minutes) |
Use Cases
Perfect for:
-
CLI tools and utilities
-
Serverless functions (AWS Lambda, etc.)
-
Microservices with fast startup requirements
-
Container images with minimal size
-
Desktop applications
Consider alternatives for:
-
Long-running server applications
-
Applications with heavy reflection
-
Development and testing (use JVM for faster iteration)
-
Applications requiring maximum performance
What’s Next?
-
Deploy your native apps → App Installation
-
Learn about containers → Remote Execution
-
Explore performance → Execution Options
-
Try different frameworks → Dependencies
Start building lightning-fast native executables with JBang! ⚡