Avoid Memory Leaks and understanding of reference in Android

Memory management is a serious problem for Android development. Memory leaks play a very important role to achieve into it. Memory leak is when an object is no longer being used but unable to be Garbage collected because it is still being referenced some other places in the application.

As a result, this unused object is occupying the memory resource even though it is not being used by the application. Too much unused objects inside application will cause not enough memory left for other active objects and finally leads application crash with OutOfMemoryError.

That means to take care of memory; you might need some different strategies such as:
Search for memory leaks (Even when things aren't failing).
Keep track of your references.


Different Ways to Memory Leak in Android

Below are few different ways which can lead the memory leak problem. So when you come across following situations, make sure you handle it properly-

Static Activities or Views
Inner Classes
Anonymous Classes
Threads or Handlers


What is Reference?     
A Reference consist addresses and class information about the object being referenced. Assigning Reference will not create distinct copies of Objects. All reference variables are referring to same Object.

Consider Example –

Book book1 = new Book();
Book book2 = book1;

book1 is reference variable which contain the address of Actual Book Object.
book2 is another reference variable
book2 is initialized with book1 means – “book1 and book2” both are referring same object , thus it does not create duplicate object , nor does it allocate extra memory.


Types of Reference

Depending upon how objects are garbage collected, references to those objects in java are grouped into 4 types.

1) Strong References
2) Weak References
3) Soft References
4) Phantom References

Let’s discuss all these reference types in detail.


1) Strong References

Strong Reference is most simple as we use it in our day to day programming. Any object which has Strong reference attached to it is not eligible for garbage collection. A typical example is:

Book book = new Book();

This kind of reference makes the referenced object not eligible for Garbage Collection. That is, whenever an object is referenced by a chain of strong Reference Objects, it cannot be garbage collected.

In general it works well as expected but below are the use case when creates a huge problem:

AsyncTask Strong Reference

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        // AsyncTask creates strong reference with the MainActivity
        new MyAsyncTask().execute();
    }
   
    private class MyAsyncTask extends AsyncTask {
        @Override
        protected Object doInBackground(Object[] params) {
           // do some stuff ;
        }
      
    }
}

Handler Strong Reference

View button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
        // Handler creates strong reference with button view
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                myTextBox.setText("Done");
            }
        }, 1000 * 10);
});

In the above example AsyncTask created in Activity onCreate() method similarly Handler inside Button View onClick(). Both has strong reference of Activity/View. If both perform background work after the Activity has been destroyed, the reference to the Activity will persist and it won’t be garbage collected until after the background task completes. Therefore a leak can occur.


2) Weak References

Weak reference object are automatically eligible for garbage collection. They are likely to be garbage collected when JVM runs garbage collector thread. When an object in memory is reachable only by Weak Reference Objects, it becomes automatically eligible for garbage collector.

Below is the example where AsyncTask has weak reference of MainActivity. So when Activity destroyed, AsyncTask is holding its weak reference and it can be collected by garbage collector. Therefore no memory leaks will happen.

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        // Pass the current activity
        new MyAsyncTask(this).execute();
    }
   
    private static class MyAsyncTask extends AsyncTask {
        private WeakReference<MainActivity> mainActivity;   
       
        // Default constructor
        public MyAsyncTask(MainActivity mainActivity) {
       
            // Create a weak reference of MainActivity
            this.mainActivity = new WeakReference<>(mainActivity);           
        }
       
        @Override
        protected Object doInBackground(Object[] params) {
           // do some stuff ;
        } 
    }
}


3) Soft References

A soft reference object is similar to weak reference object that remains in memory until memory is available and there is no risk of OutOfMemoryError. These objects will be cleared from the memory only if JVM runs out of memory.

//Strong Reference
Book book = new Book();     

//Creating Soft Reference of Book type
SoftReference<Book> softBook = new SoftReference<Book>(book);

book = null;    // Clear Book object so that it is eligible for garbage collection.

book = softBook.get();    //You can retrieve back the object which has been softly referenced because it will be garbage collected only when JVM needs memory.

Method get() returns reference to the object if object is not cleared from the memory. If object is cleared from the memory, it will return null.


4) Phantom References

Phantom reference object is directly eligible for garbage collection. JVM puts object reference in a queue called ReferenceQueue before removing from memory. The only use for phantom reference is keeping track of when object gets enqueued and when it is removed from memory.

//Strong Reference
Book book = new Book();     

//Creating Reference Queue

ReferenceQueue<Book> referenceQueue = new ReferenceQueue<Book>();

//Creating PhantomReference Reference of Book type
PhantomReference<Book> phantomBook = new PhantomReference<Book>(book,referenceQueue);

book = null;    // Clear Book object so that it is eligible for garbage collection.

book = phantomBook.get();    //It will be garbage collected. But kept in ReferenceQueue before removing it from the memory.

Conclusion


To avoid memory leaks, Reference can be one of good solution. But WeakReference is not the only solution to handle memory leak. There are some implementation designs, by which you can avoid memory leak.

To find more interesting topics on Software development follow me at https://medium.com/@ankit.sinhal

You can also find my Android Applications on play store


Comments

  1. Thank you so much for sharing this worth able content with us. The concept taken here will be useful for my future programs and i will surely implement them in my study. Keep blogging article like this.

    Android Online Training

    ReplyDelete

Post a Comment

Popular posts from this blog

Android Performance: Avoid using ENUM on Android

Android O: Impact On Running Apps And Developer Viewpoint

Smart way to update RecyclerView using DiffUtil