Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Out of Memory Error in android due to Heap Size Increasing

I am getting out of Memory error. I am working on live chat application. It is working fine but when I am running the application 1 to 2 hours on the device the heap size is increasing and when it reached at 16 MB application start hanging and being crashed after some time and showing out of memory due to heap size because the resultant heap size is greater than allocated.

I am testing my application on HTC Explorer. In my application most of the activities are using background thread and for that i am using Asnyc Task.

I am getting error like the following.

04-30 16:53:14.658: E/AndroidRuntime(5707): FATAL EXCEPTION: MagentoBackground
04-30 16:53:14.658: E/AndroidRuntime(5707): java.lang.OutOfMemoryError: (Heap Size=20167KB, Allocated=16063KB, Bitmap Size=355KB)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.util.ByteArrayBuffer.<init>(ByteArrayBuffer.java:53)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.io.AbstractSessionInputBuffer.init(AbstractSessionInputBuffer.java:82)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:98)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:173)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
04-30 16:53:14.658: E/AndroidRuntime(5707):     at com.live2support.CustomHttpClient.executeHttpPost1(CustomHttpClient.java:163)

Is there limit of heap size? how can i solve my issue?

like image 604
nikki Avatar asked Mar 22 '12 08:03

nikki


3 Answers

Your question has two parts:

1) How can I determine the size of the heap on my test device?

2) Why is my app exceeding the size of my heap?

Regarding question 1, you can determine the size of the heap on your test device directly in your code by calling:

Runtime.getRuntime().maxMemory();

See this post for additional information on that method, as well as some example heap sizes available on various devices.

Also, if you are running a rooted device, there may be a way to directly set (and check) the heap size via the interface. For example, in CyanogenMod's various versions of Android, from the Settings menu, you can select "CyanogenMod settings," and then "Performance," and then "VM heap size," and directly view (and change) the heap size for your device. Be careful, as setting the heap size too small can make your device misbehave or worse.

Regarding question 2: You have not provided enough information to diagnose your specific problem, and in any case, doing such a diagnosis second-hand is difficult at best. Your best bet for resolving this issue (and for learning something of lasting value in the process) would be to become familiar with some of the very powerful memory analysis tools available in Android (some of which are also integrated into the Eclipse IDE). I use these tools from Eclipse, so that is what I will describe below.

First of all, make sure your Eclipse version is up to date by installing the latest version of Eclipse (e.g., Indigo).

Next, in Eclipse, select Help/Install New Software, and then click the dropdown at the top and select

"Indigo - http://download.eclipse.org/releases/indigo"

Next, open the General Purpose Tools category by clicking the plus sign next to it, and select Memory Analyzer and also Memory Analyzer (Charts) [optional]. Install these tools.

Next, select Window/Preferences, and then Android/DDMS, and select the HPROF action as "Open in Eclipse." This will cause any HPROF heap dump file that you generate from DDMS to be of the appropriate format for Eclipse, and will also cause it to be automatically opened in Eclipse's Memory Analyzer (which was just installed above).

Now, open DDMS by selecting Window/Open Perspective/Other/DDMS. Select the Devices icon (looks like a phone) on the left and drag the resulting window so that it is docked somewhere you can see it easily.

Make sure that your device is connected to the PC via USB, and that your app is running.

In the Devices tab that you have just created, select your running app's process. Run the app to the point where it has occupied enough memory that you know it has leaked, but not so much that it crashes. Now, click the Dump HPROF File icon in the devices tab. After a brief delay, you'll be offered a choice of reports on your heap. Try the Leak Suspects Report to get started. This report will open in the Memory Analysis Tool. It tells you where your app is using memory. Check the various kinds of objects and see if they look bloated relative to the amount of data that you would expect them to require; if so, that may indicate a leak.

Here is a nice tutorial describing in more detail how to generate and explore your heap using DDMS and the Memory Analyzer Tool.

Back in DDMS (or the DDMS perspective in Eclipse), you can select the Allocation Tracker tab while your device is attached, and then your device from the devices tab, and then select your app's process from the list for that device. Then, in the Allocation Tracker tab, click the Start Tracking button, and then run your app's relevant operations (those that you suspect are leaking), and then click the Get Allocations button, and then select the Stop Tracking button.

This will display all allocations that have occurred while you were tracking (there are limits to the amount it will store). Clicking on any one of these will take you to the stack at the time of allocation, and clicking on any part of that stack dump will take you to the source code that was involved in the allocation.

These tools should give you some insight into what might be causing your app to leak memory.

like image 105
Carl Avatar answered Oct 11 '22 05:10

Carl


It looks like a classic memory leak. You say, that you use AsyncTask for connection. It's very easy to leak context with an AsyncTask on configuration changes (e.g. rotation of device) when you don't know how to use it properly.

First thing - I strongly recommend you watching this: http://www.youtube.com/watch?v=_CruQY55HOk

To check if you have such a memory leak, rotate your device and check how the Garbage Collector behaves. You should have something like GC_... freed 211K, 71% free 300K/1024K, external 0K/0K, paused 1ms+1ms in your LogCat nearly every time you rotate. Watch for changes in this part: 300K/1024K. If you don't have memory leaks, the first part should grow and then get smaller after a few GCs. If you have a memory leak, it will grow and grow, to the point of OOM error.

If you make sure you have a memory leak this way, what you should do is to install MAT for Eclipse, learn how to use it (with the aforementioned movie) and find out what it causes.

My personal bet would be a bad implementation of AsyncTask - do you detach it from destroyed Activity and attach it to the new one? If not, start doing it (there's an excellent example by CommonsWare) or switch to AsyncTaskLoader which does it for you and is generally a great replacement for AsyncTask (not only for loading stuff).

like image 44
Michał Klimczak Avatar answered Oct 11 '22 03:10

Michał Klimczak


Just add android:largeHeap="true" in the application tag within your manifests.

like image 28
Sayooj Avatar answered Oct 11 '22 05:10

Sayooj