Kotlin: Dive Into “inline”, Specifically About The Byte-Code Level

TC Wang
SodaLabs
Published in
3 min readNov 4, 2018

From the official document, we know the inline function is similar to C/C++ Macro, where the instruction of the function is copied-and-pasted by the compiler to the call-sites.

My Kotlin Gradle plugin version is 1.2.60

When to use inline?

Kotlin extension is resolved statically which means the instruction of the extension is sitting somewhere and calling it takes space of the stack in the runtime. Therefore, we could use the inline extension for saving the runtime overhead because both the function objects and classes need memory allocation. In addition, we could also use the inline function to hide the internal dependency from the external world, and we’ll talk about it later in this article.

Let’s take a look of the inline extension. For example, we have a runSafely inline extension for Canvas:

And here is a view using the inline extension (the call-site).

From the byte-code level in the call-site, you could see the instructions from #14 to #36 is the expansion of the inline extension.

What about not using inline?

With the same call-site except removing the inline modifier of the extension, it ends up calling a static method from the extension class byte-code, which is exactly resolved statically.

Byte-code in the call-site
Byte-code of the extension

The inline function could seal the internal dependency

In modern software development, we create modules and have modules depend on the other modules. For example:

Sometimes, you don’t want the third-party to depend on the internal shared module because that dependency plus the versioning becomes really annoying arguably. In fact, if the shared module is small enough not causing the generated code to grow too rapidly, we could hide this internal dependency from the external world with the inline function.

To really seal the internal dependency in the Android Gradle build system, we need to use the compileOnly to declare the dependency.

compileOnly project(path: ':shared-module')

The compileOnly adds the dependency to the compile classpath only. This is useful when you’re creating an Android module and you need the dependency during compilation.

The summary of this dependency sealing strategy is:

  1. Hide the dependency by using compileOnly.
  2. Embed the instructions with inline functions.

Use it with caution

The following side-by-side comparison shows you how much the generated code with the inline function versus the normal function. This sealing strategy is just a possible solution and you should use it with caution.

inline extension vs not-inline extension

BTW, I use javap command to decompile the Java classes.

javap -c -private JAVA_CLASSES_WITHOUT_DOT_CLASS_EXTENSION

Stay tuned

The inline function actually comes with two extra modifiers, the noinline and crossinline, I’ll write another article about that, still specifically about the byte-code level!

Thanks for reading and don’t hesitate to give me claps if you do learn something from the article.

--

--

TC Wang
SodaLabs

I’m an engineer who loves solving problems and science. You could find me on my LinkedIn page, https://www.linkedin.com/in