From a library-design standpoint, what binary-compatibility and tooling risks does @JvmName introduce, and when would you avoid it?
answer
- @JvmName value = public ABI name
- Changing it -> NoSuchMethodError for Java
- Kotlin recompiles fine, hiding the break
- Accessor renames break JavaBean tooling
- Guard with binary-compatibility CI checks
basics
~20 sBecause @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.
solid answer
~40 s`@JvmName` bakes a specific name into the bytecode, so for a published library that name is part of your **binary (ABI) contract** for Java consumers and anything using reflection or method handles. Renaming or dropping a `@JvmName` value is a **binary-incompatible change** — existing compiled Java callers will get `NoSuchMethodError` at runtime even though Kotlin recompiles fine. Risks: (1) breaking JavaBean introspection when accessor names diverge from `getX`/`isX`, affecting serializers and DI/reflection frameworks; (2) confusing static-analysis or doc tools that assume conventional names; (3) divergence between Kotlin call sites and Java call sites that increases cognitive load. Avoid it when a simpler Kotlin rename suffices, when consumers rely on bean conventions, or when the dual-name surface isn't worth the maintenance. Use it deliberately for genuine erasure clashes and for a polished, stable Java-facing API.
go deeper
Understands @JvmName sets the real method name; may not connect it to binary-compatibility risk.
Recognizes that renaming a @JvmName breaks Java callers and that bean tooling can be affected.
Explains the NoSuchMethodError mechanism, reflection impact, and when a plain Kotlin rename is preferable.
Sets library-wide policy: ABI checks in CI, documented Java-facing names, deliberate use only for erasure clashes and stable public surfaces.
## @JvmName names are public ABI Whatever string you pass to `@JvmName` is the **literal method/class name** in the compiled artifact. For an internal app that's harmless, but for a **published library** it becomes part of the **Application Binary Interface (ABI)** — the contract that already-compiled consumers depend on. ### The binary-compatibility trap ```kotlin // v1 @JvmName("compute") fun calculate(): Int = 42 // v2 — innocent-looking rename of the JvmName value @JvmName("computeValue") // BINARY BREAK for Java callers fun calculate(): Int = 42 ``` Java code compiled against v1 calls `compute()`. After v2 ships, that bytecode reference no longer resolves -> **`NoSuchMethodError` at runtime**. Kotlin source recompiles cleanly, which masks the danger. The lesson: **a @JvmName value is as load-bearing as the function signature itself** for binary compatibility. (Reflection / `MethodHandle` lookups by name break the same way.) ## Tooling and framework risks - **JavaBean introspection:** renaming accessors away from `getX`/`isX`/`setX` means bean-based serializers (some JSON/XML mappers), validation, and DI frameworks may stop seeing the property. Verify your serialization stack before renaming accessors. - **Static analysis / docs:** tools that assume idiomatic names may misreport or generate confusing Javadoc. - **Cognitive divergence:** Kotlin call sites use one name, Java another. On large teams this dual surface raises the maintenance burden and the chance of mistakes. ## When to use it deliberately - **Genuine erasure clashes** (generic-only-different overloads) — there's often no cleaner option than `@JvmName`. - **Polished Java-facing libraries** where a clean facade name (`@file:JvmName`) or accessor name materially improves the Java DX, and you commit to keeping it stable. ## When to avoid it - When a **plain Kotlin rename** achieves the goal without a dual name. - When consumers depend on **bean conventions** or name-based reflection. - When the API is unstable / pre-1.0 and you don't yet want to freeze names. ## Governance practices - Treat `@JvmName` values like any other public signature: cover them with **binary-compatibility validation** (e.g. an API-dump/ABI check in CI) so accidental changes are caught. - Document the Java-facing names in the public API surface. - Prefer setting names **once** and never churning them. ## Summary `@JvmName` is powerful but turns a string into a binding ABI name; renaming it breaks compiled Java/reflection consumers, and accessor renames can break bean tooling. Use it for real erasure clashes and intentional, stable Java APIs — and guard the names with binary-compat checks.
- Why is changing a @JvmName value dangerous even though the project compiles?Kotlin recompiles against the new name, but already-compiled Java/reflection consumers still reference the old name and hit NoSuchMethodError at runtime.
- How would you guard @JvmName names in a library?Add a binary-compatibility/API-dump check in CI (an ABI validator) so any change to emitted names, including @JvmName values, is flagged before release.
It's like printing a phone number on business cards: handy once, but reprint it differently and everyone holding an old card now dials a dead line.
saying these in an interview costs you the question
- Treating @JvmName values as freely changeable cosmetics
- Ignoring that Kotlin compiling fine can mask a Java binary break
- Overlooking JavaBean/serialization breakage from accessor renames
- No mention of reflection/MethodHandle name lookups breaking
- No governance or ABI-check strategy for a published library