Kotlin memory optimization from a compilation perspective

Kotlin memory optimization from a compilation perspective

Author: Yan Yongjun, Unit: China Mobile Smart Home Operation Center

Labs Guide

Today we are going to talk about Kotlin, a static programming language developed by JetBrains for modern multi-platform applications.

Kotlin can be compiled into Java bytecode or JavaScript, which is convenient for running on devices without JVM. In addition, Kotlin can also be compiled into binary code and run directly on the machine.

At Google I/O 2017, Google announced first-class support for Kotlin on Android. Currently, Kotlin has become the preferred language for Android application development.

Kotlin has many advantages over Java, such as null safety, easier-to-use Lambda expressions, support for extensions, numerous syntax sugars, etc. However, few people mention Kotlin's memory optimization for Java from a compilation perspective. Here we take a peek through decompilation.

Part 01 Java inner class holds reference to outer class

There is a common perception in Java that inner classes in Java hold references to outer classes, and improper use can easily cause memory leaks. See the following example.

We write the following code to verify.

We first create a parent class to observe whether the subclass will call the finalize method.

 public class BaseActivity extends AppCompatActivity {
@Override
protected void finalize() throws Throwable {
Log.e("yanlog", "BaseActivity finalize:" + this);
super.finalize();
}
}

We create a subclass, and in the subclass we create a Thread that will not terminate. ​

 public class TmpJavaActivity extends BaseActivity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
}
}

Through testing, we can find that the finalize method of BaseActivity can never be called, that is, the external class TmpJavaActivity can never be recycled. We use the decompilation tool jadx to observe the decompiled smail code.


From the above decompiled smail code, we can see that Java will pass the outer class object as a parameter to the inner class object. Once the inner class cannot be released, the outer class will not be released, thus causing a memory leak.

Part 02 Kotlin inner classes do not necessarily hold references to outer classes

We can write the same code above in Kotlin as follows:

 class TmpActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tmp)
val thread = Thread {
while (true) {
Thread.sleep(1000)
}
}
thread.start()
}
}

By observing the logs, we found that the external class TmpActivity can be recycled normally. Let's take a look at the smail source code.

From the above smail source code, we can see that, unlike Java, inner classes in Kotlin will be compiled into a normal class. Because the actual operation of inner classes does not depend on outer classes, after compilation, the outer class will not be passed to the inner class as a parameter of the inner class constructor, that is, the inner class will not hold the application of the outer class, so it will not cause memory leaks.

But what if the inner class actually needs to hold a reference to the outer class? Let's look at the following code.

 class TmpActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tmp)
val thread = Thread {
while (true) {
Log.e("yanlog","thread"+this@TmpActivity)
java.lang.Thread.sleep(1000)
}
}
thread.start()
}
}

Observe the decompiled smail source code as follows

From the above source code, we can see that when constructing an object of an inner class, a reference to the outer class is passed to the inner class, causing a memory leak.

From the above two examples, we can see that in Kotlin, inner classes do not hold references to outer classes unless necessary, which reduces the possibility of memory leaks compared to Java.

<<:  Application of workflow engine in vivo marketing automation

>>:  Why do you advise everyone to wait for the official version of iOS 15.6? There are four reasons

Recommend

Where is the innovation in smart TVs that keep rehashing old stuff?

Previously, people have been discussing whether O...

Help! Why do dogs always like to eat poop? The reason is not simple...

This article was reviewed by Lin Zhideng, PhD in ...

How to improve user loyalty to products?

This is a "red ocean era". Due to the r...

Technological Evolution——Witness at GITC2014

In the blink of an eye, 20 years have passed. On ...

7 Signs You're a Bad Programmer

Are you a good programmer or a bad programmer? He...

Photography, beauty, which advertising materials are timeless and creative?

I wonder if you often receive such advertising co...

Does the hesitant Changhong still have a chance to return to the throne?

After the May Day sales frenzy, the domestic colo...

A must-read for marketers! The underlying logic of hot products

What is a hot product? This is a good question an...

How do overseas bloggers calculate promotion costs? Overseas advertising rules!

Table of contents 1. How do overseas bloggers cal...

As the entrance to 1 billion traffic, will mini-program games be the key?

Summarizing 2018, which is already halfway throug...