skip to content

Multiplatform

Kotlin Multiplatform compiles shared Kotlin to JVM, Native, JS, and Wasm, using expect/actual and a source-set hierarchy to isolate what genuinely differs per platform. It comes up for mobile teams sharing logic between Android and iOS.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

explore

questions

111 · 7 sections

What is Kotlin Multiplatform (KMP), and what does it let you share across platforms?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Kotlin Multiplatform lets you write code once and run it on many platforms. You put shared code in one place, and the compiler builds it into apps for Android, iOS, web, and the desktop.

open as a page

How do expect/actual declarations work, and what are their rules and limits?

level: middleimportance: must knowfreq 65%
basics
~10 s

expect/actual is how common code says 'something with this shape exists' and each platform fills in the real version. Common code declares expect; every target must provide a matching actual.

open as a page

Explain the KMP source-set hierarchy and how intermediate source sets like appleMain enable code sharing.

level: middleimportance: should knowfreq 50%
basics
~10 s

Source sets form a tree. commonMain is the root every target uses. Intermediate sets like appleMain group related targets (iOS, macOS) so you can share code among them without duplicating it per target.

open as a page

How do you decide what belongs in commonMain versus platform code, and what architectural patterns keep the boundary clean?

level: seniorimportance: should knowfreq 40%
basics
~10 s

Put logic that doesn't depend on a specific platform (rules, data, networking) in commonMain. Put things that touch a device API in platform code. Hide platform details behind interfaces so common code stays clean.

open as a page

What compilation targets does KMP support, and what artifact does each produce?

level: seniorimportance: should knowfreq 45%
basics
~10 s

A target is a platform you build for. JVM produces bytecode, Native produces machine-code binaries (like an iOS framework), JS produces JavaScript, and Wasm produces WebAssembly. You declare targets in Gradle.

open as a page

In a Kotlin Multiplatform project, what does `actual typealias UUID = java.util.UUID` do, and why would you use it instead of writing an `actual class`?

level: juniorimportance: must knowfreq 55%
basics
~10 s

It says: on this platform, the shared expect class UUID is exactly the platform's own UUID type. You reuse an existing native type directly instead of writing a wrapper class around it.

open as a page

In Kotlin Multiplatform, what does declaring `expect class Platform` in common code and `actual class Platform` in a platform source set mean? Give a minimal example.

level: juniorimportance: must knowfreq 65%
basics
~20 s

You write a placeholder class in shared code that says 'this exists, here's its shape.' Each platform (Android, iOS) then provides the real version with the same name and members. Shared code uses it without knowing the platform.

open as a page

What are `expect` and `actual` functions in Kotlin Multiplatform, and how do you use them to expose platform-specific behavior through a common API?

level: juniorimportance: must knowfreq 70%
basics
~20 s

In shared code you write expect fun with no body, like a promise. Each platform (Android, iOS, JVM, JS) provides the real actual fun. Common code calls the function without knowing which platform fills it in.

open as a page

What are the matching rules between an `expect class` and its `actual class`? Cover constructors, members, supertypes, and the case where the actual carries members the expect did not declare.

level: middleimportance: must knowfreq 50%
basics
~20 s

The actual must have the same name, package, and matching constructors and members the expect declared, each marked actual. The actual is allowed to add extra members and extra supertypes, but those extras are invisible from shared code.

open as a page

What are the exact matching rules between an `expect fun` and its `actual fun`? Where do default parameter values and type parameters go?

level: middleimportance: must knowfreq 55%
basics
~20 s

The actual function must have the same name, the same parameters and return type, and at least the same visibility. Default values and type parameters are written only on the expect side, not repeated on actual.

open as a page

In a Kotlin Multiplatform project, what is the `commonMain` source set and what kind of code belongs in it?

level: juniorimportance: must knowfreq 70%
basics
~10 s

commonMain holds shared code that compiles to every target (JVM, iOS, JS, etc.). Put platform-independent logic there. It can only use APIs available on all targets.

open as a page

In a Kotlin Multiplatform project, what is an intermediate source set such as iosMain, and why would you create one?

level: juniorimportance: must knowfreq 60%
basics
~20 s

It is a source set shared by some targets but not all. For example iosMain is shared by iosArm64 and iosX64, so you write code once for both iOS targets instead of copying it into each.

open as a page

In a Kotlin Multiplatform Gradle build, where do you declare a dependency on a library that works on every target, and where do you declare one that only exists on the JVM?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Put shared dependencies in commonMain, inside the kotlin sourceSets block. Put a JVM-only library in jvmMain. Each source set only sees the libraries declared for it or its parents.

open as a page

In a Kotlin Multiplatform project, what does it mean that platform source sets `dependsOn` commonMain, and why is this relationship special compared to a regular library dependency?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Platform code like jvmMain depends on commonMain. This lets shared code declare a feature and each platform fill in the missing parts. It is a special link, not a normal library dependency.

open as a page

How do you write shared tests for a KMP module, and what role does `commonTest` and the `kotlin.test` library play?

level: middleimportance: must knowfreq 55%
basics
~10 s

Put shared tests in commonTest and use the kotlin.test library. Those tests run once per target, so a single test verifies behavior on JVM, iOS, JS, etc.

open as a page

In a Kotlin Multiplatform module, what artifact does the androidTarget() produce versus the iosArm64()/iosSimulatorArm64() targets, and how does each get consumed?

level: juniorimportance: must knowfreq 62%
basics
~10 s

androidTarget() builds an Android library (an AAR) that Android apps use. The iOS targets build a native framework that an Xcode/Swift app imports. Same Kotlin code, two different output packages.

open as a page

What is the Kotlin/JS IR target, and how do you enable it in a Gradle build with browser() and nodejs() environments?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Kotlin/JS lets you compile Kotlin code into JavaScript. The IR target is the modern compiler backend. In Gradle you add js(IR) and pick browser() or nodejs() depending on where the code runs.

open as a page

In a Kotlin Multiplatform build, what does declaring the jvm() target do, and what kind of artifacts does it produce?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Adding jvm() tells the compiler to build a JVM version of your code. It produces Java bytecode (.class files, usually packaged in a .jar) that runs on any Java Virtual Machine.

open as a page

What is the Kotlin/Native target, and how does running a Kotlin/Native binary differ from running Kotlin on the JVM?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Kotlin/Native compiles Kotlin straight to a native machine-code program. There is no Java Virtual Machine running it; you get a standalone executable or library that runs directly on the operating system.

open as a page

What are the wasmJs() and wasmWasi() targets in a Kotlin Multiplatform project, and how do they differ?

level: juniorimportance: must knowfreq 55%
basics
~10 s

They are two Kotlin Multiplatform targets that compile code to WebAssembly. wasmJs() runs in the browser and can talk to JavaScript; wasmWasi() runs in standalone runtimes outside the browser using the WASI system interface.

open as a page

What is the cinterop tool in Kotlin/Native, and what role does a .def file play when binding to a C library?

level: juniorimportance: must knowfreq 55%
basics
~10 s

cinterop is a Kotlin/Native tool that reads C header files and produces Kotlin code so you can call the C library from Kotlin. A .def file tells it which headers and library to use.

open as a page

On Kotlin/Native with the new memory manager, can you share a mutable object between threads, and what changed compared to the old model?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Yes. With the new memory manager you can pass and use the same object from several threads. The old model was much stricter and required freezing objects first; that is gone now.

open as a page

What is the 'new memory manager' in Kotlin/Native, and what old model did it replace?

level: juniorimportance: must knowfreq 62%
basics
~10 s

It is Kotlin/Native's modern garbage collector. It replaced an old rule that froze objects and locked them to one thread. Now you can share regular mutable objects across threads, like on the JVM.

open as a page

What does the @Throws annotation do when a Kotlin/Native function is called from Swift or Objective-C, and what happens to an exception that isn't listed?

level: juniorimportance: must knowfreq 60%
basics
~10 s

@Throws tells the Kotlin compiler which exceptions should be passed to Swift or Objective-C as errors instead of crashing. Any exception you don't list will crash the whole app.

open as a page

Explain memScoped, CPointer, and how you pass a C struct or an out-parameter to a C function from Kotlin/Native.

level: middleimportance: must knowfreq 50%
basics
~20 s

memScoped gives you a temporary native memory area that is freed when the block ends. Inside it you allocate C structs and get CPointers to them, which you can pass to C functions, including as out-parameters the C code fills in.

open as a page

In a Kotlin Multiplatform project, what does it mean that the standard library is available in commonMain, and which kinds of APIs can you safely call there?

level: juniorimportance: must knowfreq 60%
basics
~20 s

commonMain is shared code that compiles to every target. There you can use the common part of Kotlin's standard library — lists, maps, math, random, strings, numbers — but not platform-only things like Java's File or full Java reflection.

open as a page

Which core kotlinx libraries are commonly added to commonMain in a Kotlin Multiplatform project, and what does each provide?

level: juniorimportance: must knowfreq 70%
basics
~10 s

The main ones are kotlinx-coroutines-core for async work, kotlinx-serialization for turning objects to/from JSON, kotlinx-datetime for dates and times, and kotlinx-io for reading and writing bytes. All work in shared code.

open as a page

In Kotlin Multiplatform, what do the `expect` and `actual` keywords do, and why does a library use them to back one common API across targets?

level: juniorimportance: must knowfreq 70%
basics
~10 s

expect declares a shared API in common code with no body; each platform (Android, iOS, JS) provides an actual implementation. So you call one function everywhere and the right platform version runs.

open as a page

Explain Kotlin's read-only vs. mutable collection interfaces (List vs MutableList, etc.) and how the collection builders like buildList relate to them.

level: middleimportance: must knowfreq 70%
basics
~20 s

List, Set and Map are read-only views — they have no add/remove. MutableList, MutableSet, MutableMap add modification methods. buildList gives you a mutable list to fill in a lambda and returns it as a read-only List.

open as a page

How does kotlinx-serialization work in common code, and why is it suitable for multiplatform while reflection-based libraries are not?

level: middleimportance: must knowfreq 55%
basics
~20 s

You mark a class with @Serializable and a compiler plugin generates the conversion code at build time. Because it doesn't use runtime reflection, it works on platforms like iOS and JS where reflection isn't available.

open as a page

What does the @JsExport annotation do in Kotlin/JS, and why do you need it before JavaScript or TypeScript code can call your Kotlin declaration?

level: juniorimportance: must knowfreq 60%
basics
~20 s

By default Kotlin renames things when it compiles to JavaScript, so JS code can't find them. Adding @JsExport keeps the real names and generates TypeScript type info, so JS/TS can call your class or function.

open as a page

In Kotlin/JS, what is the `external` keyword for, and why do `external` declarations have no body?

level: juniorimportance: must knowfreq 55%
basics
~10 s

external tells the Kotlin compiler that something already exists in JavaScript and is implemented there. You only write its type signature, no body, so Kotlin can type-check your calls without re-implementing it.

open as a page

Which Kotlin types are 'exportable' across an @JsExport boundary, and what happens if you use a non-exportable type like Long or a Kotlin collection in an exported signature?

level: middleimportance: must knowfreq 50%
basics
~20 s

Only simple, JS-friendly types are allowed: numbers, String, Boolean, arrays, function types, and your own exported classes. Things like Long or Kotlin's List aren't exportable, so the compiler warns or errors and the .d.ts gets a fallback type.

open as a page

What is the `dynamic` type in Kotlin/JS, and how does it change the compiler's behavior compared with a normal typed value?

level: middleimportance: must knowfreq 50%
basics
~20 s

dynamic is a special Kotlin/JS type that turns off compile-time checks. You can read any property or call any method on it and the compiler won't complain — correctness is your responsibility, checked only at runtime by JavaScript.

open as a page

Compare @JsName, @JsModule, and @JsExport. When would you reach for each, especially to import from an npm package?

level: middleimportance: should knowfreq 45%
basics
~10 s

@JsExport sends Kotlin OUT to JS. @JsName renames a symbol so it matches a specific JS name (both directions). @JsModule says 'this Kotlin declaration actually lives in an npm package', importing JS INTO Kotlin.

open as a page