Skip to content

Kotlin Inline Functions ​

🧩 1. Background: Why Do We Need Inline Functions? ​

In Kotlin, higher-order functions are very common, for example:

kotlin
fun repeatAction(action: () -> Unit) {
    for (i in 1..3) {
        action()
    }
}

And you might call it like this:

kotlin
repeatAction {
    println("Hello")
}

πŸ‘‰ The problem is: Every time repeatAction is called, Kotlin must create a function object (Lambda instance) and invoke it at runtime. These operations:

  • Allocate heap memory (for the Lambda object)
  • Increase the call stack (reducing performance)

For small or frequently invoked functions, this overhead can be significant.


βš™οΈ 2. How Inline Functions Work (Key Concept) ​

When you mark a function with inline:

kotlin
inline fun repeatAction(action: () -> Unit) {
    for (i in 1..3) {
        action()
    }
}

The compiler does this at compile time:

βœ… It copies the function body directly into the call site. 🚫 No extra function object or call stack is created.

So the generated code effectively looks like:

kotlin
// The compiler-generated result is roughly:
for (i in 1..3) {
    println("Hello")
}

In other words, the function call is β€œexpanded”.


⚑ 3. Benefits of Inlining ​

BenefitDescription
πŸš€ Better performanceAvoids Lambda object creation and function call overhead
πŸ’‘ Supports non-local return (return)Allows returning directly from the outer function inside a Lambda
🧱 Compile-time expansionNo runtime cost

🚫 4. But There Are Trade-offs! ​

DrawbackDescription
πŸ“¦ Larger bytecode (code bloat)Too much inlining increases code size
⚠️ Not suitable for large functionsOnly ideal for small, frequently used functions
πŸ’­ Harder to debugStack traces may look β€œskipped” after inlining

πŸ”’ 5. noinline and crossinline ​

In an inline function, you can control how each Lambda parameter behaves.

πŸ”Έ noinline β€” Do Not Inline This Parameter ​

kotlin
inline fun runTwo(action1: () -> Unit, noinline action2: () -> Unit) {
    action1() // inlined
    action2() // not inlined, object is created
}

Used when you need to keep a Lambda as an object (e.g., to pass it to another function).


πŸ”Έ crossinline β€” Disallow Non-local Returns ​

kotlin
inline fun runCross(crossinline action: () -> Unit) {
    Thread { action() }.start()
}

Because action runs on another thread, it cannot directly return from the outer function.


🧠 6. Common Use Cases for inline ​

ScenarioExampleDescription
Higher-order functions (e.g., collection ops)list.forEach { ... }Widely used in Kotlin standard library
DSL syntaxapply, run, with, also, letReduces object creation and call layers
Small repetitive logicmeasureTimeMillis { ... }Avoids Lambda call overhead

πŸ” 7. Summary at the Bytecode Level ​

AspectRegular FunctionInline Function
Call mechanismRuntime callCompile-time expansion
LambdaCreates an objectCode is inlined, no object
PerformanceSlower (some overhead)Faster (no call stack)
Best forAny use caseSmall, frequent, higher-order functions

βœ… 8. In Short ​

Kotlin inline functions

  • Expand the function body at compile time
  • Reduce Lambda invocation and allocation overhead
  • Support non-local returns
  • Should be avoided for large functions to prevent code bloat

❓ How Java Calls Inline Functions ​

You're absolutely right β€” the behavior you observed is typical: Kotlin inline functions often cannot be called directly from Java, and here’s why πŸ‘‡


1️⃣ The Nature of Kotlin Inline Functions ​

An inline function in Kotlin is a compile-time concept, meaning:

  • The compiler inserts the function body at the call site in Kotlin code.
  • Therefore, there might be no actual method generated in the JVM bytecode (especially for inline functions with Lambda parameters).

2️⃣ When Java Can or Cannot Call Inline Functions ​

SituationCompiled BehaviorCallable from Java
Normal inline function (no Lambda params)May generate a static method but usually inlinedβœ… Yes (if method exists)
Inline higher-order function (with Lambda params)Inlined Lambdas, no standalone method generated❌ No (method signature not found)
Inline + @JvmName / @JvmStaticCan force a static method to be generatedβœ… Yes, if explicitly named

⚠️ In short: Inline functions exist for Kotlin compile-time expansion, so the JVM might not have an actual callable method for Java.


3️⃣ Solutions ​

If you want Java to be able to call it:

Method 1: Remove inline ​

kotlin
fun greet(name: String) {
    println("Hello, $name")
}

This generates a regular JVM method callable from Java.


Method 2: Use @JvmName or @JvmStatic ​

kotlin
class Utils {
    companion object {
        @JvmStatic
        inline fun greet(name: String) {
            println("Hello, $name")
        }
    }
}

Java call:

java
Utils.greet("Alice");

⚠️ Note: If the function has Lambda parameters, even @JvmStatic won’t help β€” Java can’t pass Kotlin Lambdas directly; you’d need a Java functional interface.


Method 3: Provide a Java-friendly Wrapper ​

kotlin
inline fun greetInline(name: String) { println("Hello, $name") }

// Java-compatible wrapper
fun greetForJava(name: String) = greetInline(name)

4️⃣ Summary of the Reasoning ​

  • Kotlin inline functions are compile-time constructs, not guaranteed to generate JVM methods.
  • Inline higher-order functions (with Lambdas) are fully expanded during compilation, so Java finds no method to call.
  • For Java to call Kotlin functions, there must be a real JVM-level method.

Just something casual. Hope you like it. Built with VitePress