skip to content

@JvmName & @file:JvmName

@JvmName renames an emitted method, which is how you resolve a signature clash caused by erasure, and @file:JvmName renames the facade class for top-level functions. Both exist because the JVM sees less type information than Kotlin does.

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

questions

5

What does the @JvmName annotation do, and why would you put it on a Kotlin function or property accessor that Java code will call?

level: juniorimportance: must knowfreq 55%

answer

  1. Renames the JVM/bytecode method name
  2. kotlin.jvm package annotation
  3. Java sees new name, Kotlin still uses old name
  4. Fixes nicer-Java-API and erasure clashes
  5. Works on functions and getter/setter

basics

~20 s

@JvmName changes the name that a Kotlin function, getter, or setter shows up as when called from Java. It lets you give Java a nicer name or avoid a name conflict, without changing the Kotlin name.

solid answer

~40 s

@JvmName is a compile-time annotation that overrides the method name emitted into the JVM bytecode for a function or a property accessor (getter/setter). Kotlin code keeps calling it by its original Kotlin name; Java callers see the overridden name. The two main uses: (1) make the Java-facing API read naturally, e.g. annotate a Kotlin getter so Java sees getX() with a custom name, or rename a function whose Kotlin name relies on Kotlin-only features; (2) resolve JVM signature clashes caused by type erasure (two Kotlin functions that differ only in generic type erase to the same JVM signature). It has no effect on Kotlin-to-Kotlin calls and is purely an interop/bytecode-naming tool.

code

kotlin · 7 lines
kotlin
class Money(val cents: Long) {
    @JvmName("toDollars")
    fun asDollars(): Double = cents / 100.0
}

// Kotlin:  money.asDollars()
// Java:    money.toDollars();

go deeper

for a junior

Knows @JvmName renames the Java-visible method name and that the Kotlin name is unchanged.

for a middle

Can name both use cases (nicer Java API, erasure clash) and place it on accessors with @get:/@set: targets.

for a senior

Explains it as a pure bytecode-naming compile-time tool, and reasons about its interaction with property accessors and facades.

for a principal

Frames it within an interop API-design strategy: when to expose renamed names vs. restructure the Kotlin API, and the maintenance cost of dual names.

## What @JvmName is `@JvmName` is a Kotlin annotation that lives in the `kotlin.jvm` package. It controls the **name written into the compiled `.class` file (bytecode)** for the element it annotates. It is read at compile time and erased afterward — it changes nothing at the Kotlin source level. ## What it changes vs. what it does not - **Changes:** the JVM-visible name of a function, or of a property's generated **getter/setter** methods. This is what Java callers and reflection see. - **Does NOT change:** how you call the element from Kotlin. In Kotlin you still use the original declared name. ```kotlin class Account(val ownerName: String) { @JvmName("computeBalance") fun balance(): Long = 0L } ``` From Kotlin you call `account.balance()`. From Java you call `account.computeBalance()`. ## Why you need it Two big reasons: 1. **Nicer Java-facing API.** Kotlin idioms (like a function named `balance`) may not match Java conventions; renaming gives Java a clearer call site. 2. **Avoiding JVM signature clashes.** The JVM erases generics, so two Kotlin functions with the same name that differ only in a generic type parameter compile to the **same** JVM signature, which is illegal. `@JvmName` on one of them produces distinct bytecode names so both can coexist. ```kotlin // Without @JvmName these clash on the JVM (both erase to filterValid(List)): fun List<String>.filterValid(): List<String> = filter { it.isNotBlank() } @JvmName("filterValidInts") fun List<Int>.filterValid(): List<Int> = filter { it > 0 } ``` ## Where you can put it - On a **function** (member or top-level/extension). - On a **property accessor** via a use-site target: `@get:JvmName("...")` or `@set:JvmName("...")`. - On a **file** as `@file:JvmName("...")` to rename the synthetic facade class that holds top-level declarations. The annotation does nothing for Kotlin-only consumers; it exists purely to shape the bytecode for the JVM and for Java interop.

  • Does @JvmName change how you call the function from Kotlin?
    No. Kotlin callers always use the original declared name; only the JVM bytecode name (what Java/reflection sees) changes.
  • Is @JvmName a runtime or compile-time mechanism?
    Compile-time. It instructs the Kotlin compiler what name to emit into the class file; there is no runtime behavior.

Like a stage name: the actor (Kotlin) is still called by their real name internally, but the audience (Java) sees the name on the marquee.

saying these in an interview costs you the question

  • Claiming it renames the Kotlin-visible name too
  • Thinking it has any runtime/reflection-injection behavior beyond the emitted name
  • Saying it works only on top-level functions
  • Confusing it with @JvmStatic or @JvmField
  • Believing it affects Kotlin-to-Kotlin calls

context

open as a page

Show how two Kotlin functions can produce a JVM signature clash due to type erasure, and how @JvmName resolves it.

level: middleimportance: must knowfreq 48%

basics

~20 s

Generics disappear at runtime, so List<String> and List<Int> both become plain List on the JVM. Two functions that differ only by that generic part get the same JVM signature and won't compile. Adding @JvmName to one gives it a different bytecode name, so both compile.

open as a page

What is the FooKt facade class for top-level Kotlin declarations, and how does @file:JvmName change it?

level: middleimportance: should knowfreq 42%

basics

~20 s

Top-level Kotlin functions and properties in a file get wrapped in an auto-generated class named after the file plus 'Kt' (e.g. Utils.kt becomes UtilsKt). @file:JvmName renames that wrapper class so Java calls it by a nicer name.

open as a page

How do you rename a Kotlin property's getter or setter for Java callers using @JvmName, and what subtleties come with property accessors?

level: seniorimportance: should knowfreq 35%

basics

~10 s

Properties compile to getX()/setX() methods. You can use @get:JvmName and @set:JvmName to rename those generated methods for Java, while Kotlin still accesses the property normally.

open as a page

From a library-design standpoint, what binary-compatibility and tooling risks does @JvmName introduce, and when would you avoid it?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

Because @JvmName sets the actual compiled method name, that name becomes part of your public binary contract. Changing or removing it breaks Java callers and reflection. It can also confuse tools that expect standard naming.

open as a page