Memory Management in Android Apps (Java)


One of the main issues in android development is memory management which is a slightly complicated task for Android. Apps in Android use memory as their own property i.e, they are unaware of the current resource condition of the system. In order to write an efficient code, we may use on of the four possible references, namely strong reference, weak reference, soft reference and phantom reference.


Strong Reference
A strong reference is an ordinary Java reference. For example:

RectF rectF = new RectF();

creates a new RectF and stores a strong reference to it in the variable rectF. The important part about strong references -- the part that makes them "strong" -- is how they interact with the garbage collector. Specifically, if an object is reachable via a chain of strong references (strongly reachable), it is not eligible for garbage collection. As you don't want the garbage collector destroy objects you're working on, this is normally exactly what you want.

Weak Reference
Unlike strong reference, a weak reference does not protect the referenced object from collection by a garbage collector. Weak reference objects do not prevent their referents from being made finalizable, finalized, and then reclaimed.
An object is weakly reachable when the garbage collector finds no strong or soft references, but at least one path to the object with a weak reference. For a weakly reachable object we will have the following operations:
  1. The garbage collector thread (in its next cycle) clears the weak reference of the object to the thread.
  2. After that the garbag collector places the weak reference on the queue.
  3. The garbag collector finalizes the object that in the current status has not any reference.


Weak references are most often used to implement canonicalizing mappings. A mapping is called canonicalized if it holds only one instance of a particular value. Rather than creating a new object, it looks up the existing one in the mapping and uses it.

Example: Using a weak reference may be one possible solution for avoiding memory leak. When we have a non-static inner class that refers to the outer one we probably encounter memory leak. This is the case when we have an inner Asynctask inside an activity. Generally the wrong code may be something like this:

Two mistakes have been considered in this code. The fix for the first one is presented inside it. But for the second mistake which is the issue of our discussion, we can fix it by applying a weak reference instead of strong reference used in line 29. Please consider the corrected code below:

In this corrected code, when for example the activity is destroyed (it may be due to rotation of the device), the amount of memory which is taken by destroyed activity will be reclaimed by garbag collector in its next cycle. As a special case, LeakyClass may be an AsyncTask which do a relatively longer task in the background.Then we can prevent memory leak in such way.

Soft Reference
The only real difference between a soft reference and a weak reference is that the garbage collector uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.
In fact softly reachable objects are generally retained as long as memory is in plentiful supply. When the JVM absolutely needs more memory and should reclaim memory then the garbag collector (in its next cycle) will collect the object which is only referred to it by a soft reference.

Phantom Reference
A phantom reference object is placed in its reference queue after its referent become phantom reachable (see Reachability section), i.e., the Garbage Collector adds a phantom reference to the provided reference queue after the finalize method of its referent is executed.
Unlike soft and weak references, phantom references are not automatically cleared by the Garbage Collector as they are enqueued. An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable.
A program can perform post-finalization cleanup and clear the phantom reference upon completion of the cleanup.

Phantom references have two differences from soft and weak references.
  • We can’t get a referent of a phantom reference. The get method of a phantom reference always returns null.
  • Unlike soft and weak references, we must provide a reference queue for phantom references.
There’re two common use-cases they are used for:
The first technique is to determine when an object was removed from the memory which helps to schedule memory-sensitive tasks. For example, we can wait for a large object to be removed before loading another one.
The second practice is to avoid using the finalize method and improve the finalization process.

Reachability
Going from strongest to weakest, the different levels of reachability reflect the life cycle of an object. They are operationally defined as follows:
  1. An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.
  2. An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
  3. An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.
  4. An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it.
  5. Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.

Comments