1. Overview

In this tutorial, we’re going to get familiar with a few ways to get the name of the currently executing function in Kotlin.

The first approach is the most idiomatic way if we’re targeting Java 9. In addition to that, we also will explore a few hacky ways that will definitely work but come with their drawbacks.

2. The Stack-Walking API

Java 9 introduced the Stack-Walking API to lazily navigate through the stack frames of the current thread. This API provides a better way to traverse the stack frames as it does not eagerly capture all the frames, which is costly. Also, it doesn’t allocate extra unnecessary objects or defines new classes as opposed to alternative approaches.

The top frame in each stack represents the last function call. Therefore, we can use this API and get the function name from the top stack frame:

fun functionNameWithStackWalker(): String? {
    return StackWalker.getInstance().walk { frames ->
        frames.findFirst().map { it.methodName }.orElse(null)
    }
}

The walk() method accepts a Function that receives a Stream of StackFrames as the input. This way, we can walk through all frames one by one in a lazy manner and extract the intended information from each one.

In the above function, we only need the first or top frame, so we’re calling the findFirst() method. Also, each StackFrame encapsulates the details for a particular frame. In this case, we used the methodName property (getMethodName() in Java) to find the current function name.

Let’s make sure that this function works as expected:

val name = functionNameWithStackWalker()
assertEquals("functionNameWithStackWalker", name)

3. Anonymous Inner Class

We can define an anonymous inner class inside a function definition. As the Class API in Java allows accessing the enclosing member details, we can also get the current function name by defining an anonymous inner class:

fun functionNameWithAnonymousInnerClass(): String {
    return object {}.javaClass.enclosingMethod.name
}

The Java equivalent to Kotlin’s object {} declaration is:

new Object() {};

So, we’re defining an anonymous inner class inside a function. Consequently, it’s possible to get the enclosing function name using the enclosingMethod property (getEnclosingMethod() method in Java):

val name = functionNameWithAnonymousInnerClass()
assertEquals("functionNameWithAnonymousInnerClass", name)

This approach is a little bit less efficient and also less idiomatic as we’re creating a totally unnecessary object. So, we should go with this one only if our target JVM version is less than 9.

4. Capturing Stack Traces

The getStackTrace() method on the Thread class returns an array of stack trace elements representing the stack dump of a thread. We can use this method and the Thread.currentThread() method together to capture all stack trace elements for the current thread:

fun functionNameWithStackTraces(): String {
    return Thread.currentThread().stackTrace[1].methodName
}

When using Thread.currentThread().getStackTrace(), the getStackTrace() method will be on top of the stack. Therefore, the second array element would represent the enclosing function.

Since the getStackTrace() method captures a lot of stack trace elements eagerly, this is the least efficient approach. So we should avoid using this one as much as we can.

5. Conclusion

In this short tutorial, we saw a few different approaches to get the name of the currently executing function.

As usual, all the examples are available over on GitHub.