Make writing a habit together! This is the sixth day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

1. Review several Java references

Let’s review the way references are used in Java:

  • Strong referenceReferences are common in Java, for example Object object = new Object();.

As long as an object has a strong reference associated with it, the JVM will definitely not reclaim that object, even if it is OutOfMemory and would rather throw an OutOfMemory error than reclaim that object

  • A weak reference private WeakReference<GCOwer> rf = new WeakReference<>(new GCOwer());

It will be collected immediately once the GC has occurred

  • Soft references private SoftReference<GCOwer> rf2 = new SoftReference<>(new GCOwer());

The Major GC can only be collected if it is out of memory

In summary, because weak references are collected whenever GC occurs regardless of memory, we can use this feature to listen for gc to occur in our application.

2. Weak reference listener GC:

public class GCCheck {
    private WeakReference<GCOwer> rf = new WeakReference<>(new GCOwer());

    public class GCOwer {

        @Override
        protected void finalize(a) throws Throwable {
            super.finalize();
            Log.i("GCCheck"."finalize: app gc occur");

            rf = new WeakReference<>(newGCOwer()); }}}Copy the code

We manually constructed a WeakReference instance, WeakReference, which holds the GCOwer object.

Then we override the Finalize () method of GCOwer class;

Once GC occurs, the GCOwer object held by WeakReference will be recycled. When GCOwer is recycled, the call of finalize() method will be triggered, and we can count the frequency of GC execution in this method.

It should be noted that in finalize(), we need to re-instantiate a WeakReference

and assign it to rf, because the previous WeakReference has been collected, and if we want to continue listening to gc, we need to re-create a WeakReference instance of WeakReference

3. Field test

Define a class that allocates a sufficiently large array of 1000 * 10000:

class Dump1 {
    val data = Array(1000 * 10000) {
        return@Array "$it".repeat(10)}}Copy the code

Then call the Activity onCreate:

override fun onCreate(savedInstanceState: Bundle?). {  
    val dump1 = Dump1()
}
Copy the code

At this point, look at the logcat message:

You can see the crazy logging in finalize() of the GCOwer class, which represents the frequent gc occurrences in the application.

4. Application in Android source code

thenActivityThreadWill call:

BinderInternal uses weak references to implement GC listening, and ActivityThread adds GC listening callbacks to handle Activity reclaims when memory reaches a certain threshold and meets a number of other criteria.

To learn more about Activity recycling, see the reference article below.

Refer to the article

If the App is in the foreground, the Activity will not be recycled.

This article analyzes the Activity related memory reclamation mechanism from both the application layer and the system layer