Learning -Xjvm-default=all and Xjvm-default=all-compatibility in Kotlin
Kenji Tomita
Posted on July 19, 2020
Introduced on the official Kotlin blog about generating default methods in interfaces. -Xjvm-default=all
, -Xjvm-default=all-compatibility
options are avaiable in Kotlin 1.4. To use advantage of these, you need to target Java 8, which allows you to generate methods in your interface by default. Let's try it.
Try using -Xjvm-default=all
The following code is the sample code. Define sleep()
in the Animal
interface. The Dog
class inherits the Animal
interface and calls Dog().sleep()
in main()
.
// Main.kt
fun main() {
Dog().sleep()
}
class Dog : Animal
interface Animal {
fun sleep() {
println("The animal sleeps.")
}
}
This time, I'm using IntelliJ IDEA, which allows you to easily reference the bytecode of Kotlin code and decompile it. For the procedure, select Tools
-> Kotlin
-> Show Kotlin Bytecode
.
Then, the bytecode is displayed, so if you click the Decompile
button, it will be decompiled.
So far, I have introduced the decompilation procedure. Let's set the -Xjvm-default=all
option. Select IntelliJ IDEA
-> Preferences
-> Build, Execution, Deployment
-> Compiler
-> Kotlin Compiler
. Select Language version
and API version
to 1.4
, set -Xjvm-default=all
to Additional command line parameters
, and finally set Target JVM version
to 1.8
.
Now let's decompile. The following code is the decompiled code.
// MainKt.java
import kotlin.Metadata;
@Metadata(
mv = {1, 4, 0},
bv = {1, 0, 3},
k = 2,
xi = 2,
d1 = {"\u0000\b\n\u0000\n\u0002\u0010\u0002\n\u0000\u001a\u0006\u0010\u0000\u001a\u00020\u0001¨\u0006\u0002"},
d2 = {"main", "", "algo"}
)
public final class MainKt {
public static final void main() {
(new Dog()).sleep();
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
}
// Dog.java
import kotlin.Metadata;
@Metadata(
mv = {1, 4, 0},
bv = {1, 0, 3},
k = 1,
xi = 2,
d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0003"},
d2 = {"LDog;", "LAnimal;", "()V", "algo"}
)
public final class Dog implements Animal {
}
// Animal.java
import kotlin.Metadata;
@Metadata(
mv = {1, 4, 0},
bv = {1, 0, 3},
k = 1,
xi = 2,
d1 = {"\u0000\u0010\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u0002\n\u0000\bf\u0018\u00002\u00020\u0001J\b\u0010\u0002\u001a\u00020\u0003H\u0016ø\u0001\u0000\u0082\u0002\u0006\n\u0004\b!0\u0001¨\u0006\u0004À\u0006\u0001"},
d2 = {"LAnimal;", "", "sleep", "", "algo"}
)
public interface Animal {
default void sleep() {
String var1 = "The animal sleeps.";
boolean var2 = false;
System.out.println(var1);
}
}
As you can see, default
is set in sleep()
of the Animal
interface.
Try using -Xjvm-default=all-compatibility
Let's use -Xjvm-default=all-compatibility
. Change -Xjvm-default=all-compatibility
to Additional command line parameters
.
Let's decompile.
// MainKt.java
import kotlin.Metadata;
@Metadata(
mv = {1, 4, 0},
bv = {1, 0, 3},
k = 2,
xi = 2,
d1 = {"\u0000\b\n\u0000\n\u0002\u0010\u0002\n\u0000\u001a\u0006\u0010\u0000\u001a\u00020\u0001¨\u0006\u0002"},
d2 = {"main", "", "algo"}
)
public final class MainKt {
public static final void main() {
(new Dog()).sleep();
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
}
// Dog.java
import kotlin.Metadata;
@Metadata(
mv = {1, 4, 0},
bv = {1, 0, 3},
k = 1,
xi = 2,
d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0003"},
d2 = {"LDog;", "LAnimal;", "()V", "algo"}
)
public final class Dog implements Animal {
}
// Animal.java
import kotlin.Metadata;
import org.jetbrains.annotations.NotNull;
@Metadata(
mv = {1, 4, 0},
bv = {1, 0, 3},
k = 1,
xi = 2,
d1 = {"\u0000\u0010\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u0002\n\u0000\bf\u0018\u00002\u00020\u0001J\b\u0010\u0002\u001a\u00020\u0003H\u0016¨\u0006\u0004À\u0006\u0001"},
d2 = {"LAnimal;", "", "sleep", "", "algo"}
)
public interface Animal {
default void sleep() {
String var1 = "The animal sleeps.";
boolean var2 = false;
System.out.println(var1);
}
@Metadata(
mv = {1, 4, 0},
bv = {1, 0, 3},
k = 3,
xi = 2
)
public static final class DefaultImpls {
public static void sleep(@NotNull Animal $this) {
$this.sleep();
}
}
}
default
is set for sleep()
of the Animal
interface. You can also see that the DefaultImpls
are generated. This time, I introduced how to use each option. For more details, please refer to Kotlin official blog.
Posted on July 19, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 23, 2024