Lambda expression is not using invokedynamic

Hi,

I tried lambda expression in Kotlin (1.5.10) with target Java 1.8. I set the compiler option -Xlambdas=indy in maven pom file. But, in Java bytecode, it still uses the wrapper class but not the invokedynamic.

And also documentation states that SAM by default uses invokedynamic (from 1.5). But, I checked, it still creates a wrapper class.

Could you please let me know, where I am going wrong?

Thanks

My Example code

fun interface Vehicle {
fun start()
fun stop() {
println(“Vehicle is stopped”)
}
}

fun main() {
val vehicle = Vehicle { println(“Car is started”) }
vehicle.start()
vehicle.stop()
}

1 Like

Try a normal lambda instead of a fun interface, because fun interfaces are compiled as wrapper classes because they specifically have to implement that interface AFAIK, although I think there’s plans to change that.
Edit: fun interfaces, according to the Kotlin docs, should use indy by default since 1.5.10:

SAM adapters via invokedynamic

Kotlin 1.5.0 now uses dynamic invocations ( invokedynamic ) for compiling SAM (Single Abstract Method) conversions:

The new implementation uses LambdaMetafactory.metafactory() and auxiliary wrapper classes are no longer generated during compilation

Perhaps check that your Jvm target version is 1.8?

yes, my JVM target is 1.8.

1 Like

I found the problem. My example was not a pure Kotlin functional interface, because it contains two methods one abstract and one default implementation. I tried with the pure Kotlin functional interface and by default, it generates the bytecode with “invokedynamic”. Below is the example. And for the lambda, with just -Xlambda=indy compiler options is enough to generate the bytecode with “invokedynamic” for the lambda expression. (Initially, it did not generate, I am not sure why, but after that, I removed OptIn compiler options, and after I compiled using “mvn clean” command it worked)

fun interface Vehicle {
fun start()
}

fun main() {
val vehicle = Vehicle { println(“Car is started”) }
vehicle.start()
}

1 Like

Have you also added -Xjvm-default=all flag? It’s required if you want to have fun interfaces treated as such also from the Java perspective.

2 Likes

No, I did not add that initially. However, I tried now that option, and it works even for my initial example code. that’s amazing.

Thank you :slight_smile:

1 Like