13

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?

Praveenkumar
  • 25,322
  • 23
  • 89
  • 166
nikki
  • 3,058
  • 3
  • 22
  • 29
  • 1
    Post some code. My guess is you using large Bitmaps inside Custom List. – Venky Mar 22 '12 at 08:06
  • i am not using bitmap in my application.i Have some images in drawable folder and i am using them only which are not much 15 to 20 images i have. – nikki Apr 24 '12 at 10:15
  • do you really need all the history of chat at runtime, or you are maintaining these chat history in array or in collection object or your list view is too large. You can use dynamically growing list view . – Animesh Sinha May 02 '12 at 07:27
  • at com.live2support.CustomHttpClient.executeHttpPost1(CustomHttpClient.java:163) -- you are doing something that occupy good amount of memory everytime..try to free that memory as soon you use that..even everywhere the objects,arraylist,bitmaps clear from memory as soon you use it..once use assign null and call System.gc(); to indicate a flag to garbage collector. – MKJParekh May 02 '12 at 07:28
  • yes i am calling System.gc(); everywhere. – nikki May 02 '12 at 07:33
  • Anieeh i did not need the history of chat all time but somecase i need to show history of chat. – nikki May 02 '12 at 07:34
  • Calling System.gc() is in most cases not a solution. Read http://stackoverflow.com/questions/2414105/why-is-it-a-bad-practice-to-call-system-gc – Michał Klimczak May 02 '12 at 07:56

5 Answers5

12

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.

Community
  • 1
  • 1
Carl
  • 14,895
  • 5
  • 52
  • 53
7

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).

Michał Klimczak
  • 11,170
  • 7
  • 55
  • 92
  • Also I had a weird problem with OOM error which appeared only when I started my app from the debugger. When started normally with launcher icon the memory leak didn't occur: http://stackoverflow.com/questions/10305037/leaking-memory-with-actionbarsherlock – Michał Klimczak May 02 '12 at 08:00
4

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

mech
  • 2,368
  • 5
  • 26
  • 34
Sayooj
  • 41
  • 2
  • 3
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – mech Feb 26 '16 at 06:48
1

Your heap size limit is device-dependent. On a 2.x device, I expect about 20 or 32 MB is your limit. See Android heap size on different phones/devices and OS versions for more information on heap sizes.

From your stack trace, it looks like com.live2support.CustomHttpClient.executeHttpPost1() is at the center of your problem.

Community
  • 1
  • 1
Sparky
  • 8,267
  • 1
  • 27
  • 41
  • Usual stuff. I'd try things in this order: 1. visual inspection of the code. Also maybe add your function to this question at SO so others can check it out. 2. step through the code using a source-level debugger. 3. Use DDMS if 2 doesn't do the trick. http://developer.android.com/guide/developing/debugging/ddms.html – Sparky May 02 '12 at 07:30
0

This can be done by two ways according to your Android OS.

  1. You can use android:largeHeap="true" in application tag of Android manifest to request a larger heap size, but this will not work on any pre Honeycomb devices.
  2. On pre 2.3 devices, you can use the VMRuntime class, but this will not work on Gingerbread and above See below how to do it.
VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE);

Before Setting HeapSize make sure that you have entered the appropriate size which will not affect other application or OS functionality. Before settings just check how much size your app takes & then set the size just to fulfill your job. Dont use so much of memory otherwise other apps might affect.

Reference: http://dwij.co.in/increase-heap-size-of-android-application

Web Developer in Pune
  • 1,684
  • 16
  • 19