~ 5 minutes read featured in kotlin weekly issue #193
no time? jump straight to conclusion
Lazy is one of the delegated properties kotlin offers. Depending on which version of kotlin you use the lazy function call is compiled differently.
This post is about how Kotlin 1.4M1 optimizes the lazy function compilation and how you can leverage the optimization also in Kotlin 1.3.
A lot of Kotlin 1.3 (tested with 1.3.60/61) code that contains lazy function calls get compiled into classes that contain KProperties arrays.
A one liner like this:
val myLazyString:String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { "hi" }
can be compiled and decompiled. The decompiled code (using procyon) would be:
static final /* synthetic */ KProperty[] $$delegatedProperties;
@NotNull
private final Lazy myLazyString$delegate;
static {
$$delegatedProperties = new KProperty[] {
(KProperty)Reflection.property1((PropertyReference1)
new PropertyReference1Impl((KDeclarationContainer)
Reflection.getOrCreateKotlinClass((Class)
Dearlazy.class),
"myLazyString", "getMyLazyString()Ljava/lang/String;")) };
}
@NotNull
public final String getMyLazyString() {
final Lazy myLazyString$delegate = this.myLazyString$delegate;
final KProperty kProperty = Dearlazy.$$delegatedProperties[0];
return (String)myLazyString$delegate.getValue();
}
The decompiled classes code includes a KProperty array $$delegatedProperties and a lazy object (see also KotlinConf 2019 presentation: Kotlin Uncovered by Chet Haase & Romain Guy (lazy)). In this specific example, such an array might not be needed because the string definition within the lazy function call is just a string.
Kotlin 1.4M1 lazy optimization
Using Kotlin 1.4M1 you can compile the same one liner kotlin code as above. The decompiled class would be:
@NotNull
private final Lazy myLazyString$delegate;
@NotNull
public final String getMyLazyString() {
return (String)this.myLazyString$delegate.getValue();
}
public Dearlazy() {
this.myLazyString$delegate =
LazyKt.lazy(LazyThreadSafetyMode.SYNCHRONIZED,
(Function0)Dearlazy$myLazyString.
Dearlazy$myLazyString$2.INSTANCE);
}
While the lazy object remains, the KProperty array is not part of the decompiled code it anymore. The code looks much slimmer.
Can I use the Kotlin 1.4M1 lazy optimization in Kotlin 1.3 as well?
Yes. My test results about compiling and decompiling with Kotlin 1.3.70 & Kotlin 1.4M1 are the same:
@NotNull
private final Lazy myLazyString$delegate;
@NotNull
public final String getMyLazyString() {
return (String)this.myLazyString$delegate.getValue();
}
public Dearlazy() {
this.myLazyString$delegate =
LazyKt.lazy(LazyThreadSafetyMode.SYNCHRONIZED,
(Function0)Dearlazy$myLazyString.
Dearlazy$myLazyString$2.INSTANCE);
}
more decompilation details: 1.3.70 && 1.4M1
Side track: JVM decompiler
There are multiple options to compile and decompile Kotlin code.
I used gradle 5+ to compile Kotlin code in this context. For class decompilation I used procyon. This is simply because I like the syntax highlighting procyon offers.
That comes with a price. A terminal command:
cd build/classes/kotlin/main/info/lotharschulz/lazy && procyon Dearlazy && cd ../../../../../../..
produced the results I shared above.
However, a call like
procyon build/classes/kotlin/main/info/lotharschulz/lazy/Dearlazy
produces different results. Those did not allow the analysis above.
In comparison, javap produced the same results regardless which of the 2 following calls I used:
javap -c -p build/classes/kotlin/main/info/lotharschulz/lazy/Dearlazy
cd build/classes/kotlin/main/info/lotharschulz/lazy/ && javap -c -p Dearlazy
I rated syntax highlighting higher that saving cd commands. That is a personal choice. I found java decompiler interesting as one of a lot of java decompiler listings.
Conclusion
Kotlin 1.4M optimizes delegated properties. Lazy functions as one of the delegated properties are compiled into much slimmer classes – arrays like $$delegatedProperties will not be generated if not needed.
According to my test, you can leverage this optimization with Kotlin 1.3.70 as well.
Links
- Delegated properties
- Kotlin
- KotlinConf 2019 presentation: Kotlin Uncovered by Chet Haase & Romain Guy (javap)
- KotlinConf 2019 presentation: Kotlin Uncovered by Chet Haase & Romain Guy (procyon)
- Jetbrains kotlin blog – what to expect in kotlin 1.4 and beyond – delegated-properties (2019/12/)
- KotlinConf 2019 presentation: Kotlin Uncovered by Chet Haase & Romain Guy (what to expect in Kotlin 1.4)
- 8 best java decompiler in 2019
- (not related still I like: Jetbrains kotlin blog – what to expect in kotlin 1.4 and beyond – trailing-commas)
Update 2020 04 15
- fix the link in Kotlin 1.3.71 and changed the tag to Kotlin 1.3.70
- Kotlin 1.3.72 link added
nice read!
thanks!
Enjoy Easter!