Memory issues without hitting Heap Limit? - android

So, for my particular application, I have a pretty large list of items in my ListView, upwards of 10,000+ items. I don't keep all the items in memory, but rather I lazy-load them around 150 at a time from a database. I'm using an LRU cache to only keep the last 500 or so items around, but the problem is that even so, sooner or later I run into memory issues.
This error eventually starts spamming my Logcat when I move around the list view:
03-15 12:36:45.114: ERROR/dalvikvm-heap(8971): 86400-byte external allocation too large for this process.
03-15 12:36:45.114: ERROR/GraphicsJNI(8971): VM won't let us allocate 86400 bytes
Once I get into this state, if I click on an item to go to the next info activity, it'll crash with an OutOfMemory exception. Before this, it's perfectly fine and can go into the info activity just fine.
Looking at my memory usage in DDMS, the heap size is only around 6, and actual usage is only around 5mb when the errors start popping up. The info activity does contain some images and stuff, but definitely not an extreme amount, and only bumps up the usage by like 100kb or so. This is no where near the usual 16mb heap limit that I've heard tossed around.
Any ideas?

Related

Is this memory leakage

I am planning to hunt any memory leak in my Android App. After searching through different blogs, it seems like MAT is a good tool for that.
Before proceeding further, I just want to make something clear. When I check allocated heap memory in memory monitor tab of android studio, i can see the allocated memory increases by ~1 MB (from 16MB of initial allocation) each time I rotate my device. This, most probably suggests some leaks.
However in the process, at any stage, whenever I click on Garbage Collection button in memory minitor window to force GC, the allocated memory comes down to near the initial stage 16MB+ (sometimes requires 2 back to back click when allocated memory expands beyond 30 MB).
My question is, does this behavior suggests that I don't have any leaks due to strong references? If GC can collect those extra chunks, how important is that to check the issue?

android - RAM consumption increases while overwriting large objects

To the downvoters: I'm not pasting any code since my question is generalized, I'll post some as soon as someone request it.
In my application I load a user's playlist in form of quite a large JSONArray on Activity's start, parse and display this data in a ListView. If the user presses the Update button the whole operation gets repeated, same objects get overwritten. I noticed that the RAM amount used by the app gets increased randomly between 0.4 and 1 MB with each update. I'm trying to figure out the reason, the same memory addresses just get overwritten with new data, why does the RAM consumption grow? I also tried to set all used objets to null before doing the update, this decreased the RAM amount used but only by about 100KB.
I have no explanation for that issue, since there're same variables which just get overwritten. The size of server response has not changed. Any ideas how to fix this memory leak?
Because the same memory addresses don't get overwritten. You're creating new objects that take up new memory, and both copies will stick around until the old one is garbage collected. You can speed that along by making sure there's no dangling references to the old data anywhere in the app (by explicitly setting them to null), or by calling System.gc (although that has large negative penalties to it). But growing in that situation is expected. What shouldn't be happening is that if you do an hprof after getting the result several times you should never see the total number of instances of your array increasing unbounded. If you do, then you need to track up the chain of owners and see who's still hanging on.

Android OutOfMemoryError when parsing csv file

I have an app that downloads a csv file online then saves it locally so the app will work even if it is offline. My problem is when the user closes the app then opens it again immediately, the app hangs while parsing the saved csv file and throws OutOfMemoryError. However, I noticed that when I open the app again after a few minutes it works just fine.
The downloading, parsing and saving are done on separate threads.
What can be the solution to this?
One possibility: out-of-memory errors can have more to do with an overworked GC than with an actual shortage of memory. If you allocate large pieces of memory, then free them, then allocate even larger pieces, you get to a point where you have a lot of large bits of free memory taking up space but unusable because they're not large enough. The GC is frantically trying to move things around and merge these pieces into one contiguous block for the next allocation, but rather than look bad because it's taking too long, it will just throw an OutOfMemory exception, even though 90% of memory is theoretically available (and will be available if you can give it a minute).
In your case, I'd suspect ArrayList. It keeps an array of references. As you add entries, it adds to the array. When it runs off the end, it allocates a new, bigger, one and frees the old one. These discards pile up if you keep it busy. Hashtables have similar problems. LinkedList and TreeMap don't, because they work with small bits of memory.
I don't know too much about Android, but I'm guessing the app doesn't really close when you close it briefly, so when you restart it it's the same free-memory-fragmented execution as before. If you wait a while it may be a new execution. Even if it's not, the GC has had time to clean things up and you're fine.
The solution you want is probably to force a garbage collection (System.gc()) each time you "start up" your system. It gives the GC a chance to put everything in order before allocating space for you, and it won't take long. In a sense, you're giving the GC permission to lock up your program for half a second, which it would not do on its own. (And if it did, it would pick an awkward time to do it--while the user's entering text, say.)
Avoiding large arrays by using linked collections is another solution, but arrays are fast and when you can spare a half-second of the user's time there's no reason to switch.
Hope this helps. If it's not the problem this time, maybe it will be next time.
Addition: Unfortunately, System.gc() is just a "suggestion". It may not be doing the job we hoped it would do. Or you may be getting into trouble after the call. The other big fix I should have mentioned before would be to set the initial size on ArrayList very large, if that is what your are using. Making it two or three times the size it needs to be will probably save you ten times that amount of memory over a run--and save time, too. This works for any array-based structure (hash tables and plain arrays). Beyond that, pointer-based structures like LinkedList will not have this problem if you can get around their disadvantages.

Analyzing memory usage using MAT. Trying to interpret what I see

I'm auto-testing my app by loading the same screen over and over. I make heap dumps every 400 screen loads and then try to see whether I have leaks. The screen makes 3 network calls (it loads two XML files and one bitmap file). I noticed this object:
39 instances of "org.apache.http.impl.conn.tsccm.ConnPoolByRoute", loaded by "" occupy 6,506,440 (51.72%) bytes.
This is after 800 screen loads. The "funny" thing is that after 400 loads there were 75 instances totaling to about 13MB!
In fact, the strangest thing is, that the heap keeps increasing from 12MB to almost 27MB (I'm not sure if it will go over the 64MB that the device has!). When I stop the automatic loading and repeatedly press "Cause GC" in the Eclipse DDMS Heap section, it keeps drecreasing the "Allocated" memory until I'm almost down to 6MB!? The question I have is, how come the heap size keeps increasing even though it seems I'm not using all that memory. Is it because my memory is defragmented? Should I be able to converse more memory if I don't keep creating new objects but keep an object pool? Should GC not cause an OOM when I reach the critical value of 64MB and should it try to do its best more? I feel kind of uneasy that it would get so close to 64MB. I wish the GC would be more punctual :)
Hope someone can help.
Best,
Joris

Android grow heap frag case

I'm working on an app to streaming music from internet... My app does many things and it's structured in this way: I have a tab view and every view is allocated in memory so every time I navigate through tabs I find again the previous status ( every tab can also open a webview to find information about songs, news etc in internet ).. all that grows memory occupation but makes the app very user friendly... After having paid attention to avoid memory leaks following the Android guide, I tried to look at the heap occupation and I found that my app allocates max 3.5MB of memory and the heap size allocated is 4.5 - 4.6 MB... I'm working on the emulator .. They are not so much I think, but sometimes my app is restarted founding in LogCat a strange message like
Grow heap ( frag case ) to 3.373 for 19764-byte allocation
What is it? an emulator issue? or something else? Am I using too much memory?
Thank you in advance for any help :)
The maximum heap size depends on the device (you can get that value by calling Runtime.getRuntime().maxMemory()), but it's probably around 32MB. In order to save memory, Android doesn't allocate maximum memory to every app automatically. Instead it waits until the app need more memory and then gives it more heap space as needed until it's reached the max. I believe that's the Grow heap message you see.
If you do a lot of memory allocation and freeing, you may run into fragmentation problems. Wikipedia has a decent description here, but basically means that you might have the required memory available, just not all in one chunk. Hence the need to grow the heap.
So to answer your questions, it's probably not an emulator issue, it's just the nature of your program, which sounds a little memory heavy. However this isn't a bad thing. I don't think using 3-5MB for multiple tabs with webviews is too much.

Categories

Resources