Nucleus
Performance & native

Performance and native runtimes

Nucleus builds the same Kotlin source into two runtimes — a GraalVM native image or a JDK 25 image with an AOT cache — selected from one Gradle DSL.

Nucleus compiles the same Kotlin source into two runtimes, and you choose which one to produce at build time: a GraalVM native image, or a standard JDK 25 image with an ahead-of-time (AOT) cache. Both are driven by the same Gradle DSL, so switching between them changes the build output, not your code.

The two runtimes

The runtimes differ in how the application is compiled and what it ships with, which leads to different startup and throughput characteristics.

GraalVM Native ImageJDK 25 + AOT cache
CompilationAhead-of-time, closed worldJIT at runtime, open world
Java runtimeNone; self-contained binaryBundled JRE plus AOT cache
Reflection and JNIStatic metadata onlyDynamic, no restrictions
Artifactnucleus.graalvm-runtimenucleus.aot-runtime

A GraalVM native image starts quickly and holds a smaller resident set, because it is compiled ahead of time and bundles no JVM. The JDK runtime reaches higher sustained throughput once HotSpot's JIT has warmed up on hot paths; the AOT cache shortens that warmup by reusing class-loading and compilation work from a previous run.

Choose a runtime

  • GraalVM Native Image — background utilities, menu-bar apps, CLI-style desktop tools, and sandboxed targets such as the App Store or MSIX. Startup is fast, the installer is small, and no Java runtime ships with the app.
  • JDK 25 + AOT cache — long-running, IDE-like tools, data-heavy workloads, plugin hosts, and anything that relies on dynamic behavior such as scripting engines, ByteBuddy, or custom class loaders. HotSpot's JIT pays off once hot paths warm up, and the AOT cache removes most of the warmup cost.
  • Both — the two can coexist in one project. A team might ship a GraalVM build to the App Store and a JDK build with an AOT cache for direct download.

Switch between runtimes

Both runtimes are configured in the nucleus.application block. Enabling graalvm produces a native image; setting enableAotCache produces a JDK image with an AOT cache.

build.gradle.kts
nucleus.application {
    mainClass = "com.example.MainKt"

    // Produce a GraalVM native image.
    graalvm {
        isEnabled = true
        imageName = "myapp"
    }

    // Or produce a JDK 25 image with an AOT cache.
    nativeDistributions {
        enableAotCache = true
    }
}

Both blocks can be present at once. Select which runtime a build produces per build type or per CI matrix entry, or produce both and let users choose.

Supporting modules

The native builds rely on a few modules that supply platform metadata and OS integration:

  • Native access — how Nucleus supplies GraalVM's reflection, resource, and JNI metadata so you don't hand-write JSON.
  • Native code in Kotlin — write the native side in Kotlin/Native and call it from the JVM through a generated FFM bridge.
  • Native HTTPHttpClient, OkHttp, and Ktor wired to the OS trust store.
  • Native SSL — the OS keychain as the trust-anchor source.

What's next

  • GraalVM Native Image — the full Gradle DSL, automatic metadata, Gradle tasks, and CI wiring.
  • AOT cache — JDK 25's Project Leyden, connected to Gradle in one line.
  • Runtimes — the architecture behind the two backends.