OpenJDK vs GraalVM vs Amazon Corretto 2026: Which JDK Should You Use?

TL;DR — 3-Sentence Verdict

If you are running a long-lived, throughput-heavy service on a VM or container and want the simplest, free, fully-supported option, use Amazon Corretto (or Eclipse Temurin) — both are production-grade OpenJDK builds with free LTS patches. If you are building serverless functions, CLI tools, or startup-time-critical microservices and can tolerate the AOT build complexity, use GraalVM Native Image, which cuts cold-start times from seconds to milliseconds and halves memory usage. Vanilla OpenJDK (Oracle builds) is best left to developers who want the canonical reference implementation and are comfortable with only 6 months of patch support per release.

Quick Comparison Table — OpenJDK vs GraalVM vs Amazon Corretto

Feature OpenJDK (Oracle) GraalVM CE GraalVM EE Amazon Corretto
Vendor Oracle Oracle (open-source) Oracle (commercial) Amazon Web Services
License GPLv2 + CE GPLv2 + CE Oracle NFTC / Commercial GPLv2 + CE
Native Image No Yes (free) Yes (optimized) No
Startup Time (JVM) ~300–600ms ~300–600ms ~300–600ms ~280–550ms
Startup Time (Native) N/A 5–80ms 5–50ms N/A
Memory Footprint High (JVM heap) Medium (JVM) / Low (Native) Low (Native optimized) Medium-High
LTS Support 6 months per release Follows OpenJDK LTS Extended commercial Free, multi-year LTS
Polyglot (JS, Python, Ruby) No Yes (Truffle) Yes (Truffle, optimized) No
Best For Reference builds, dev Serverless, microservices Enterprise native apps AWS workloads, enterprises
Cost Free Free Commercial license Free

Introduction: Why JDK Choice Matters More Than Ever in 2026

In 2026, "install Java" is no longer a simple answer. The Java ecosystem has fragmented into over a dozen distributions, each making different trade-offs between performance, licensing, cloud-native capabilities, and long-term support. For most of the 2000s and early 2010s, developers defaulted to Oracle JDK without much thought. Then came Oracle's 2019 licensing change — requiring a commercial license for Oracle JDK in production — and the landscape shattered into competing distributions almost overnight.

Today, three names dominate the conversation: OpenJDK (the canonical open-source reference implementation), GraalVM (Oracle's polyglot, native-compilation powerhouse), and Amazon Corretto (AWS's enterprise-hardened, freely-supported distribution). Each solves a different problem, and picking the wrong one can mean either unnecessary complexity or leaving significant performance gains on the table.

The stakes are real. If you are running a Spring Boot microservice on AWS Lambda, the difference between a Corretto JVM cold start (~1,500ms) and a GraalVM Native Image cold start (~60ms) can be the difference between your application feeling snappy or visibly laggy for end users — and a measurable difference in AWS bill. Conversely, if you are running a Kafka consumer processing millions of records per day, GraalVM Native Image's limited JIT capabilities can actually hurt throughput compared to a well-tuned Corretto JVM.

This guide gives you the complete picture: architecture, benchmarks, Spring Boot compatibility, cloud behavior, and clear "when to choose" guidance for each distribution. We also cover the second-tier players — Eclipse Temurin, Azul Zulu, and Microsoft Build of OpenJDK — so you have the full map.

OpenJDK Deep Dive

What Is OpenJDK?

OpenJDK is the official open-source reference implementation of the Java SE Platform. When the community or the JCP (Java Community Process) ratifies a new Java version, OpenJDK is the codebase that embodies that specification. Oracle leads the OpenJDK project and employs many of its core engineers, but contributions come from Red Hat, Google, Microsoft, Amazon, SAP, and dozens of independent contributors.

An important distinction: Oracle produces builds of OpenJDK — the binaries you download from jdk.java.net — but these are not the same as "Oracle JDK" (the commercial distribution). Oracle's OpenJDK builds are free under GPLv2 + Classpath Exception. However, they only receive updates for 6 months — the duration of one Java release cycle. Once Java 25 ships, Java 24 Oracle OpenJDK builds go dark.

Release Cadence

Since Java 9, Oracle has shipped a new Java version every 6 months (March and September). Every ~two years, one release is designated LTS (Long-Term Support). The current LTS versions are:

  • Java 21 — LTS, released September 2023, mainstream until 2028+
  • Java 17 — LTS, released September 2021, still widely used
  • Java 25 — LTS, expected September 2025, successor to 21

Non-LTS releases (22, 23, 24) are stepping stones. Most enterprises skip them entirely and stay on LTS versions where vendor distributions provide long-term patches.

Who Builds on OpenJDK?

OpenJDK is the source — every major JDK distribution is essentially a build of OpenJDK with its own patches, tooling, and support model. This means switching between Corretto, Temurin, Zulu, or Microsoft Build typically requires no code changes. GraalVM is the notable exception: it extends OpenJDK's compiler infrastructure with its own optimizing JIT (Graal compiler) and AOT pipeline.

Strengths of Vanilla OpenJDK Builds

  • Closest to the spec — canonical reference for Java features
  • First to ship new Java versions (before vendor builds catch up)
  • Ideal for development, experimentation, and CI pipelines where you always want the latest

Weaknesses

  • Only 6 months of patches per release — not suitable for production LTS workloads
  • No commercial support from Oracle unless you buy Oracle Java SE Subscription
  • No performance enhancements beyond what the community merges upstream

GraalVM Deep Dive: The Game Changer

What Makes GraalVM Different?

GraalVM is not just another OpenJDK build — it is a fundamentally different runtime that replaces the standard HotSpot C2 JIT compiler with the Graal compiler (written in Java itself), and adds an entirely new compilation mode: Ahead-of-Time (AOT) native image compilation.

At its core, GraalVM ships in two modes:

  • JVM mode — runs Java bytecode like any JDK, using the Graal JIT instead of C2. Performance is comparable or slightly better than HotSpot for many workloads.
  • Native Image mode — compiles your entire application (bytecode + libraries + JDK subset) into a standalone native binary at build time. No JVM at runtime.

GraalVM Native Image: How It Works

The native-image tool performs a closed-world analysis — it traces all reachable classes, methods, and fields from your application entry points and includes only what is provably needed. The result is a self-contained ELF/Mach-O binary that:

  • Starts in 5–80ms (vs 300–2000ms for JVM warm-up)
  • Uses 50–70% less heap memory at startup compared to equivalent JVM applications
  • Has no JIT compilation overhead — all code is pre-compiled native machine code
  • Produces smaller Docker images (no JRE required — just the binary + libc)

AOT vs JIT — The Real Trade-off

Dimension JIT (HotSpot / GraalVM JVM mode) AOT (GraalVM Native Image)
Startup Time 300ms – 3,000ms 5ms – 80ms
Peak Throughput Very high (profile-guided optimization) Lower (no runtime profiling)
Memory at Startup 150MB – 500MB RSS 30MB – 120MB RSS
Build Time Seconds (javac) 1–10 minutes (native-image)
Reflection / Dynamic Class Loading Full support Requires configuration (reflect-config.json)
Best Workload Type Long-running, high-throughput services Serverless, CLI, short-lived containers

Polyglot and the Truffle Framework

GraalVM's second superpower is its Truffle language implementation framework. Truffle lets language implementors write an AST interpreter for any language, and GraalVM's partial evaluation will JIT-compile it to near-native performance automatically. This enables:

  • GraalJS — JavaScript (Node.js compatible) running on the JVM, sharing heap with Java objects
  • GraalPy — Python 3.x runtime, dramatically faster than CPython for many workloads
  • TruffleRuby — Ruby with JIT compilation
  • Espresso — Java-on-Java (a Java bytecode interpreter written in Truffle, enabling hot-reload for native images)

Polyglot is mostly relevant to platform teams and language implementors. Most application developers use GraalVM purely for its native image capabilities.

Spring Boot Native Image Example

# Build Spring Boot 3.4 native image with GraalVM 21
# Prerequisites: GraalVM 21+, native-image tool installed

# Using Maven
./mvnw -Pnative native:compile

# Using Gradle
./gradlew nativeCompile

# The resulting binary (no JVM required at runtime)
./target/my-service

# Typical output:
# Started MyServiceApplication in 0.072 seconds (process running for 0.092)
# (vs. ~2.4 seconds on JVM)

Spring Boot 3.x includes the Spring AOT engine that generates proxy-free, reflection-minimized versions of your application context specifically for GraalVM native compilation. Most common Spring features (JPA, Security, Web MVC, WebFlux) are fully supported. Libraries with heavy reflection (some older third-party libraries) may require additional reflect-config.json hints.

GraalVM CE vs EE

GraalVM Community Edition (CE) is free and open-source under GPLv2 + CE. It includes Native Image, Truffle, GraalJS, and the Graal JIT. GraalVM Enterprise Edition (EE) is Oracle's commercial offering, adding Profile-Guided Optimization (PGO) for native images, G1-tuned GC for native, and compressed references — typically yielding 10–20% better throughput in native mode. For most teams, CE is sufficient unless you are running latency-sensitive, high-volume native services.

Amazon Corretto Deep Dive

What Is Amazon Corretto?

Amazon Corretto is AWS's no-cost, production-ready distribution of OpenJDK. Amazon introduced it in 2019 after Oracle's licensing changes created uncertainty in the enterprise Java ecosystem. Corretto is what AWS uses internally to run its own services — from S3 to DynamoDB control planes — which means it is battle-tested at extraordinary scale.

Corretto is 100% TCK-compliant (passes the Java SE Technology Compatibility Kit), meaning it is a certified Java SE implementation. You can drop it in anywhere you were using Oracle JDK or any other OpenJDK distribution without changing a single line of code.

What Amazon Adds On Top of OpenJDK

Corretto is not a plain OpenJDK repackage. Amazon's JVM team backports critical patches and applies performance improvements specifically tuned for AWS infrastructure:

  • Quarterly security patches — Amazon commits to patching LTS versions quarterly, even between OpenJDK patch cycles, addressing CVEs quickly
  • Performance patches — optimizations for x86-64 and ARM (Graviton) architectures, including vectorization improvements and GC tuning
  • Graviton-native builds — ARM64 binaries tuned for AWS Graviton2/3 processors, which provide 20–40% better price-performance than x86 on many workloads
  • Amazon Linux integration — ships as a first-class package in Amazon Linux 2 and 2023 repos (amazon-linux-extras install java-openjdk21)
  • JFR improvements — additional JVM Flight Recorder events for AWS-specific diagnostics

LTS Support Timeline

Java Version Corretto Support Until Status
Java 8May 2026End of Life
Java 11September 2027Active LTS
Java 17October 2029Active LTS (recommended)
Java 21September 2031Active LTS (recommended)
Java 25~2033Upcoming LTS

Why Enterprises Choose Corretto

  • Zero cost — free for production use, forever, with no per-CPU or per-seat licensing
  • AWS ecosystem integration — default JDK on Lambda (Java runtime), Elastic Beanstalk, Amazon EMR, and CodeBuild
  • Graviton optimization — switching from x86 Corretto to Graviton Corretto can cut EC2 costs 20–40% with equal or better performance
  • Regulatory confidence — TCK-certified, backed by AWS SLAs, suitable for financial services and healthcare compliance requirements
  • Predictable patching — quarterly cadence maps cleanly to enterprise change-management windows

Limitations of Corretto

  • No native image support — cannot replace GraalVM for serverless AOT scenarios
  • No polyglot runtime — purely Java/JVM
  • Slightly behind GraalVM EE in raw JIT optimization for compute-heavy workloads

Other Major JDK Distributions (Brief Comparison)

Beyond the big three, several other distributions are worth knowing:

Distribution Vendor License LTS Best For
Eclipse Temurin Eclipse Adoptium GPLv2 + CE Free, multi-year Vendor-neutral, community-preferred production JDK
Azul Zulu Azul Systems Free (CE) / Commercial Free LTS + paid extended Teams wanting optional commercial support SLAs
Microsoft Build of OpenJDK Microsoft GPLv2 + CE Free LTS Azure workloads, Windows-heavy shops
Azul Zing / Platform Prime Azul Systems Commercial Yes (paid) Ultra-low latency (C4 GC — pause-free), trading systems
Oracle JDK Oracle NFTC (free for production in 2023+) Yes (Oracle support) Teams already in Oracle ecosystem with OCI/Java SE subscriptions
Eclipse Temurin deserves special mention as the community's de facto standard vendor-neutral distribution. It is built and tested by the Eclipse Adoptium Working Group (Microsoft, Red Hat, IBM, Azul, Google as members), TCK-certified, and the default recommendation for teams that want a stable, politically neutral, free LTS JDK without AWS or Microsoft vendor tie-in.

Benchmark Results: OpenJDK vs GraalVM vs Corretto (2026 Data)

The following benchmarks represent representative results from Spring Boot 3.4 microservice workloads, serverless cold-start tests, and throughput benchmarks. Hardware: AWS Graviton3 c7g.large (2 vCPU, 4 GB RAM) and AWS Lambda with 512 MB memory.

Metric OpenJDK 21 (JVM) Corretto 21 (JVM) GraalVM 21 (JVM mode) GraalVM 21 (Native)
Startup Time (Spring Boot 3.4) ~2,450ms ~2,280ms ~2,100ms 68ms
RSS Memory at Start (MB) ~320 MB ~295 MB ~310 MB ~72 MB
Peak Throughput (req/s, Wrk benchmark) ~18,400 ~19,200 ~19,800 ~15,600
Lambda Cold Start (512MB) ~1,600ms ~1,480ms ~1,450ms ~62ms
Lambda Warm Invocation (p99 latency) ~12ms ~11ms ~11ms ~14ms
Docker Image Size (distroless) ~210 MB ~210 MB ~215 MB ~38 MB
Native Image Build Time N/A N/A N/A ~4–7 minutes
P99 Latency (JVM warm) ~18ms ~16ms ~15ms ~13ms
Benchmark notes: These figures are representative averages from Spring Boot 3.4 REST API workloads (Hibernate JPA, PostgreSQL connection pooling, 50 concurrent clients). Peak throughput figures are after JVM warm-up (~5 minutes). Native image throughput is lower because the Graal AOT compiler cannot apply profile-guided optimizations that HotSpot JIT learns at runtime. Your results will vary based on application complexity and GC configuration.

Spring Boot 3.4 Integration: JVM vs Native

Spring Boot 3.x introduced first-class support for GraalVM Native Image via the Spring AOT (Ahead-of-Time) processing engine. Understanding how each JDK behaves with Spring Boot is essential for modern Java development.

Spring Boot + Corretto / OpenJDK / Temurin (JVM Mode)

For traditional JVM deployments, all three behave nearly identically. Spring Boot's auto-configuration, dependency injection, and component scanning work exactly as expected. You get the full flexibility of reflection, dynamic proxies, and runtime classpath scanning.

# Standard Spring Boot application.properties for JVM mode
# No special configuration needed for Corretto or OpenJDK

spring.application.name=my-service
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
server.port=8080

# Typical JVM flags for Corretto on containers
# -XX:+UseG1GC -XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError

Spring Boot + GraalVM Native Image

Spring Boot 3.x ships with the spring-boot-starter-parent (3.x) which includes the Spring AOT Maven/Gradle plugin. When you run a native build, Spring AOT pre-processes your application context at build time, generates proxy-free bean definitions, and produces GraalVM reachability metadata automatically for all Spring-managed components.

<!-- pom.xml: Enable native image compilation -->
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.4.1</version>
</parent>

<profiles>
  <profile>
    <id>native</id>
    <build>
      <plugins>
        <plugin>
          <groupId>org.graalvm.buildtools</groupId>
          <artifactId>native-maven-plugin</artifactId>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>
# Build the native executable
./mvnw -Pnative native:compile -DskipTests

# Result: ./target/my-service (self-contained binary, no JVM needed)
# Run it:
./target/my-service --spring.datasource.url=jdbc:postgresql://db:5432/mydb

What Works and What Doesn't with Native Image

  • Fully supported: Spring Web MVC, Spring WebFlux, Spring Data JPA, Spring Security, Spring Actuator, Spring Batch, most Micrometer metrics
  • Needs hints: Libraries using heavy reflection (Jackson works out of the box; older ORMs may need reflect-config.json)
  • Not supported: Dynamic class loading at runtime, runtime bytecode generation (CGLIB dynamic proxies replaced by Spring's build-time proxy generation), JVM attach API
Practical tip: Use @RegisterReflectionForBinding and @ImportRuntimeHints annotations (Spring 6+) to register reflection metadata without hand-editing JSON config files. Most Spring Boot starter libraries ship their own GraalVM hints — check the GraalVM Reachability Metadata repository for community-contributed hints.

Cloud and AWS Lambda: Where GraalVM Native Wins Decisively

AWS Lambda's billing model charges for duration from invocation start to completion, and cold starts (where a new Lambda container is initialized) include full JVM startup time. For a typical Spring Boot + Corretto Lambda:

  • Container init: ~200ms
  • JVM startup: ~300ms
  • Spring context load: ~1,000–1,500ms
  • Total cold start: 1,500–2,000ms

This means the first user request after a cold start can be visibly slow — a real UX problem for user-facing APIs. With GraalVM Native Image:

  • Container init: ~200ms
  • Native binary startup: ~40–80ms
  • Total cold start: 240–280ms — 80% reduction

AWS officially supports GraalVM native binaries on Lambda through the Custom Runtime (provided.al2023) runtime. You package your native binary as a bootstrap executable in your deployment ZIP or container image.

# Lambda custom runtime — Dockerfile for GraalVM native image
FROM ghcr.io/graalvm/native-image:ol9-java21-22.3 AS build
WORKDIR /app
COPY . .
RUN ./mvnw -Pnative native:compile -DskipTests

FROM public.ecr.aws/amazonlinux/amazonlinux:2023
COPY --from=build /app/target/my-service /var/runtime/bootstrap
RUN chmod +x /var/runtime/bootstrap
CMD ["/var/runtime/bootstrap"]

Lambda: Corretto vs GraalVM Cost Comparison

Scenario Corretto 21 (JVM) GraalVM Native Image
Cold Start (512MB Lambda) ~1,480ms ~62ms
Warm Invocation (p50) ~8ms ~9ms
Memory for 1K req/s 512MB minimum 128–256MB sufficient
Monthly cost (1M invocations, 300ms avg) ~$2.80 (512MB) ~$0.98 (128MB)
SnapStart compatible Yes (with Corretto 21 runtime) N/A (native starts fast already)
AWS Lambda SnapStart (available for Corretto 11/17/21 runtimes) is worth mentioning as a middle ground. SnapStart takes a snapshot of the initialized Lambda execution environment and restores it on cold starts, reducing cold start time to ~200–400ms without requiring GraalVM. For teams not ready to invest in native image build pipelines, SnapStart on Corretto is an effective compromise.

When to Choose Each JDK

Choose Amazon Corretto (or Eclipse Temurin) When...

  • You need free, long-term-supported production JDK with minimal operational overhead
  • You are running on AWS infrastructure (EC2, ECS, EKS, Beanstalk) — Corretto is the default and optimized for Graviton
  • Your application is a long-running service (API server, Kafka consumer, batch processor) where JIT warm-up pays off in throughput
  • You use dynamic class loading, runtime bytecode generation, or frameworks not yet compatible with native image
  • You need JVM Flight Recorder, heap dumps, and attach-based profiling in production
  • Your team has limited DevOps bandwidth and wants to avoid native image build pipeline complexity
  • You are on Java 8 or 11 (legacy codebase) and cannot migrate to 17/21 yet

Choose GraalVM Native Image When...

  • You are building AWS Lambda functions, Azure Functions, or Google Cloud Functions where cold start matters
  • You are building CLI tools that must start instantly (like a Java-based Kubernetes operator or database migration tool)
  • You are building microservices in containers that scale to zero and cold-start frequently
  • Your memory budget is tight — native images use 50–70% less RSS than equivalent JVM applications
  • You need smaller Docker images (10–40MB native binary vs 200MB+ JRE-based image)
  • You are using Quarkus or Micronaut — both frameworks are designed specifically around native image from the ground up
  • Your application is Spring Boot 3.x with standard starters and you can accept a 4–7 minute build time in CI/CD

Choose OpenJDK (Oracle Builds) When...

  • You are a developer experimenting with new Java features (24, 25) immediately upon release
  • You are running short-lived CI/CD build environments where long-term support is irrelevant
  • You contribute to the OpenJDK project itself and need the reference build
  • You are doing JVM internals research or JDK benchmarking
  • Not recommended for production without a vendor distribution's LTS patches

Frequently Asked Questions

1. Is GraalVM better than OpenJDK?

GraalVM is not universally better — it depends on the workload. GraalVM Native Image gives dramatically faster startup and lower memory usage, making it ideal for serverless and microservices. However, for long-running, throughput-intensive services, standard OpenJDK with JIT compilation often achieves higher peak throughput after warm-up. GraalVM's JIT (Graal compiler) is comparable or slightly faster than HotSpot C2 for some workloads, but the real differentiation is native image — not JIT.

2. Is Amazon Corretto free to use in production?

Yes, absolutely. Amazon Corretto is 100% free for production use, including commercial applications. There are no per-CPU fees, subscription requirements, or usage restrictions. Amazon provides no-cost long-term support for Java 11, 17, 21, and upcoming LTS versions, making Corretto one of the most cost-effective OpenJDK distributions available in 2026.

3. What is GraalVM Native Image and when should I use it?

GraalVM Native Image is an ahead-of-time (AOT) compiler that compiles Java bytecode into a standalone native binary at build time. It eliminates JVM startup overhead, shrinks memory footprint significantly, and eliminates cold-start latency. Use it for AWS Lambda functions, container microservices that scale to zero, CLI tools, and any workload where sub-100ms startup time is a hard requirement. Avoid it for workloads that rely on dynamic class loading or require peak JIT-optimized throughput.

4. Which JDK should I use for Spring Boot 3.x?

For traditional Spring Boot deployments (JVM mode), Amazon Corretto 21 or Eclipse Temurin 21 are the top recommendations — both are free, LTS, and stable. For Spring Boot 3.x Native (Spring AOT + GraalVM native compilation), you need GraalVM 21 or GraalVM 23+. Native compilation reduces Spring Boot startup from 2–4 seconds to under 100ms, which is a transformative improvement for serverless and container environments.

5. Does OpenJDK have long-term support?

Oracle's OpenJDK builds only provide 6 months of support per release. For long-term support (LTS), you need a vendor distribution: Amazon Corretto (free), Eclipse Temurin (free), Azul Zulu (free CE / paid EE), Microsoft Build of OpenJDK (free), or Oracle JDK (now free under NFTC for production). These vendors backport security patches and maintain LTS versions (17, 21, 25) for 5–8 years. Never run Oracle's raw OpenJDK builds in production without a plan for quarterly patching.

Conclusion

The JDK choice in 2026 is not a single right answer — it is a spectrum of trade-offs matched to your workload profile.

Amazon Corretto (or its community equivalent Eclipse Temurin) is the safe, proven, zero-cost choice for the vast majority of production Java workloads. It is what you should use by default for services that run continuously, need long-term patching, and operate on standard JVM assumptions. On AWS, Corretto's Graviton optimization and Lambda SnapStart support make it even more compelling.

GraalVM Native Image is the future for cloud-native, event-driven, and startup-latency-sensitive Java. The complexity cost — AOT build pipelines, reflection hints, incompatible libraries — is real, but the ecosystem has matured dramatically. Spring Boot 3.x, Quarkus, and Micronaut all provide first-class native image support. For serverless functions and microservices that scale to zero, native image is no longer experimental — it is production-ready.

Vanilla OpenJDK belongs in development environments and CI pipelines, not production. Use vendor distributions that commit to multi-year patching.

The winning strategy for most teams in 2026: use Corretto 21 on JVM for your core services, and progressively migrate your Lambda functions and lightweight microservices to GraalVM Native Image as your build pipeline matures. The performance gains are worth the investment.

Stay Updated with Techoral

Get the latest Java and JDK guides delivered to your inbox.