Kotlin and the JVM

This section documents Kotlin 2.4.x on the JVM, as published at kotlinlang.org, which is the reference these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against kotlinlang.org before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

Kotlin is often introduced through Android, and Android is indeed the platform where Google has recommended Kotlin as the preferred language since 2019 — but Kotlin is a general-purpose JVM language first. This page states that plainly before the rest of this section gets into language details, because the framing changes how several later features read (all-open classes, coroutines, the build tooling).

Kotlin/JVM Compiles to the Same Bytecode Java Does

kotlinc compiles .kt source to standard JVM .class files — the identical bytecode format javac produces from .java source. There is no Kotlin-specific virtual machine, no interpreter, and no separate runtime beyond a small kotlin-stdlib.jar (extension functions, Sequence, coroutine primitives, and similar library code) that ships alongside your compiled classes like any other JAR dependency.

Because of this, Kotlin/JVM:

  • Runs on any JVM that already runs Java — the same HotSpot/OpenJDK/GraalVM you already deploy to, with the same class loading, garbage collection, JIT compilation, and profiling/monitoring tools (JFR, async-profiler, VisualVM) — nothing Kotlin-specific to install on the runtime side.

  • Is fully Java-interoperable in both directions: Kotlin code calls Java classes/libraries directly (Kotlin was designed from day one to sit on top of the existing Java ecosystem with no wrapper layer), and Java code calls Kotlin classes just as directly, since a compiled Kotlin class is a JVM class like any other.

  • Works with any Java build tool — Maven, Gradle — via a compiler plugin (see Build and Tooling).

Where Kotlin/JVM Runs

Because it is JVM bytecode, Kotlin/JVM runs wherever a JVM does, well beyond Android:

  • Servers — Spring Boot officially supports Kotlin as a first-class language; see Java or Kotlin for Spring Boot?.

  • CLI tools and scripts — kotlinc compiles a standalone executable jar, and Kotlin scripting (.kts) runs snippets without a full build.

  • Desktop applications — via Compose Multiplatform for a modern declarative UI, or plain JavaFX/Swing called directly from Kotlin.

  • Build tooling — Gradle itself supports build scripts written in Kotlin (the Gradle Kotlin DSL, build.gradle.kts), which is how most new Gradle projects (Kotlin and Android alike) are configured today.

  • Android — Google’s officially preferred application language since 2019 — covered in depth in Kotlin for Android, but it is one deployment target among the several above, not Kotlin’s defining one.

Kotlin/JVM in the Wider Kotlin Multiplatform Picture

The Kotlin compiler front end is shared, but its back end can target more than the JVM under Kotlin Multiplatform (KMP):

  • Kotlin/JVM — this section’s subject: JVM bytecode.

  • Kotlin/JS — compiles to JavaScript, for browser or Node.js code.

  • Kotlin/Native — compiles ahead-of-time to native machine code (LLVM-based) for platforms without a JVM, most notably iOS, but also native Linux/Windows/macOS binaries.

  • Kotlin/Wasm — compiles to WebAssembly.

KMP lets a project share business-logic Kotlin source across all four back ends while writing platform-specific UI/IO code natively per platform — typically to share code between an Android app (Kotlin/JVM) and an iOS app (Kotlin/Native) from one codebase. This section documents Kotlin/JVM only; Kotlin/Native and Kotlin/JS are out of scope beyond this orientation.

flowchart LR SRC(["Kotlin source (.kt)"]) --> KC[["Kotlin compiler front end"]] KC --> JVM["Kotlin/JVM
→ .class bytecode"] JVM --> SERVER["Server
(Spring Boot)"] JVM --> DESKTOP["Desktop
(Compose MP, JavaFX)"] JVM --> CLI["CLI tools & scripts"] JVM --> ANDROID["Android
(Jetpack, Compose)"] JVM --> JAVAINTEROP["Existing Java code
(bidirectional interop)"] KC --> JS["Kotlin/JS
→ JavaScript"] KC --> NATIVE["Kotlin/Native
→ native binary (e.g. iOS)"] KC --> WASM["Kotlin/Wasm
→ WebAssembly"] style JVM fill:#4c8bf5,stroke:#2c5aa0,color:#fff style ANDROID fill:#3ddc84,stroke:#1b8a4c,color:#0b3d24

See Also