In Kotlin, variables are not just placeholders for data — they represent how values and objects are created, stored, and managed in memory through the JVM. Understanding this helps developers write more efficient, predictable, and safe code.
Variables exist to make programs dynamic and adaptable:
Kotlin runs on the JVM, so its variable handling relies on the JVM’s memory architecture. When Kotlin code is compiled, it is converted into Java bytecode, where every variable and object follows well-defined memory allocation rules.
During compilation, Kotlin variable names are not stored literally. Instead, the compiler assigns each one a specific memory slot or offset:
The JVM divides memory into two main areas — stack and heap — and Kotlin follows the same principle:
The way a variable stores and accesses data depends on its type:
Int, Boolean, Double) store the value directly in the stack. Copying such a variable copies the value itself.String, List, custom classes) store a pointer to the heap object. Copying the variable only copies this pointer, not the underlying object.String?) may store a null reference to represent “no object.”fun demo() {
val age: Int = 25
var name: String = "Kotlin"
var nickname: String? = null
nickname = "Kotliner"
}
When no stack variable or object reference points to a heap object, it becomes unreachable and is automatically cleaned by the JVM’s Garbage Collector. Kotlin developers don’t need to manually free memory — the GC efficiently reclaims it and may compact memory to optimize performance.
| Aspect | Primitive / Value Type | Reference / Object Type |
|---|---|---|
| Stored In | Stack (directly) | Stack reference → Heap object |
| Copied By | Value | Reference |
| Mutability | Independent copy | Shared reference |
| Garbage Collection | Not applicable | Automatic by GC |
Kotlin uses two main keywords for variable declarations:
val – Immutable variable; cannot be reassigned after initialization.var – Mutable variable; can be changed anytime.val language = "Kotlin" // Immutable
var version = 2.0 // Mutable
Kotlin also supports type inference, so you can skip the explicit type if it’s obvious from the assigned value.
fun main() {
val language: String = "Kotlin"
var version: Double = 1.8
println("Language: $language")
println("Version: $version")
version = 2.0
println("Updated Version: $version")
var nickname: String? = null
println("Nickname: $nickname")
nickname = "Kotliner"
println("Updated Nickname: $nickname")
}
Output:
Language: Kotlin
Version: 1.8
Updated Version: 2.0
Nickname: null
Updated Nickname: Kotliner