anmpout / osmdroid

Automatically exported from code.google.com/p/osmdroid
0 stars 0 forks source link

OutOfMemoryException #156

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
First, I thought it's the problem in my application, but now I know how to get 
this exception also with osm-samples, which I've downloaded from downloads.

What steps will reproduce the problem?
1. Start 'OpenMap'. If your location is hidden, activate from context menu 'My 
Location'
2. Begin to scroll, to zoom in and out
3. Close 'OpenMap' and start with step 1

What is the expected output? What do you see instead?
I don't expect any OutOfMemoryExceptions, but they are there

What version of the product are you using? On what operating system?
3.0.1.
The strange thing is, this issue doesn't occurs on phones with Android 1.5, but 
on all phones with Android version higher than 1.5.

Please provide any additional information below.

As I already wrote in discussions, it's probably the problem of google:
http://code.google.com/p/android/issues/detail?id=8488
But there are also some solutions

Original issue reported on code.google.com by ti...@ametov.net on 6 Feb 2011 at 12:59

GoogleCodeExporter commented 9 years ago
This has been reported many times before. The most relevant previous issue is 
probably issue 54. My comment of Jul 06, 2010 still applies now.

Your steps to reproduce above weren't very specific, but I think I followed 
them okay and didn't see the issue.

I've spent a lot of time in the past year looking into this and I think I've 
done enough to make osmdroid usable. But the ideas in the google issue you 
referenced look interesting. I do still get OOME occasionally, so I'll agree 
that there could still be room for improvement. If anyone wants to suggest a 
specific patch to improve memory then I'll be glad to look at it.

osmdroid already has some calls to Bitmap.recycle and System.gc, although I 
don't think they help.  All the lifecycle stuff is out of the control of 
osmdroid - it's in the app that uses osmdroid.  The samples could do it, but 
it's probably better if the samples just demonstrate the normal usage without 
all kinds of os bug workarounds.

Original comment by neilboyd on 6 Feb 2011 at 7:58

GoogleCodeExporter commented 9 years ago
Hi Neil,

did you get a look to logs and memory usage following steps I've described 
above?

I'm getting outofmemory-logs on HTC-Desire and Motorola Milestone.

> osmdroid already has some calls to Bitmap.recycle and System.gc
There are two System.gc() and two Bitmap.recycle() calls

Have you read about this solution?
http://mobi-solutions.blogspot.com/2010/08/how-to-if-you-want-to-create-and.html

This guy suggests to set bitmap to null after recycle.

> All the lifecycle stuff is out of the control of osmdroid - 
> it's in the app that uses osmdroid
Yes, you are right, but this issue occurs because of bitmaps. What I mean, I 
can make everything with bitmaps I've created myself in my application, but is 
there some posibility to get access on bitmaps osmdroid created?

UPD:
And I've got them also in emulator, but you need really pation, to get it. I 
guess, the most problem is zooming, that zooming causes outofmemory-exception. 
But it's only a guess

Original comment by ti...@ametov.net on 7 Feb 2011 at 10:23

GoogleCodeExporter commented 9 years ago
Hello Neil,

I found a fast and simple way to reproduce the OutOfMemory exception using the 
OpenStreetMapViewer sample, but there are some conditions and preparations:

1. Android 2.0 or higher
2. start OpenStreetMapViewer
3. zoom into the map
4. enable my location
5. send a valid geolocation to the device, the current location must be shown 
in the map (the "person"-icon is visible)

After that, do the following in a loop:

1. use the back-key to return to the desktop
2. Start the OpenStreetMapViewer again

After some time, the OutOfMemory exception occurs. With Android 2.2, I had to 
do only 6 iterations to reproduce the error. Other OS version may require more 
iterations (up to 20 for Android 2.0), with Android 1.6 or lower I could not 
reproduce the problem at all.

Because the heap values shown by DDMS didn't look bad, I used the following 
command to get more memory info:

    adb shell dumpsys meminfo

Here is the result with Android 2.2, after 6 iterations:

** MEMINFO in pid 253 [org.osmdroid] **
                    native   dalvik    other    total
            size:    15932     5063      N/A    20995
       allocated:    15423     2939      N/A    18362
            free:      424     2124      N/A     2548
           (Pss):     1840     4101    13425    19366
  (shared dirty):     1436     3996     1572     7004
    (priv dirty):     1692     1968    12144    15804

As you can see, it's the native memory usage wich makes the problems. Without 
enabling my location, the memory usage after 30 iterations is:

** MEMINFO in pid 458 [org.osmdroid] **
                    native   dalvik    other    total
            size:     8220     3591      N/A    11811
       allocated:     5115     2479      N/A     7594
            free:      388     1112      N/A     1500
           (Pss):     1217     2930     3067     7214
  (shared dirty):     1464     4048     1040     6552
    (priv dirty):     1044     1236     2456     4736

This looks OK. I know the the native memory is most likely allocated by the 
tile bitmaps, but I have no idea why enabling the MyLocationOverlay causes the 
allocated native memory to increase so much.

Another strange fact:
If I do 5 iterations with an enabled MyLocationOverlay, then the used native 
memory is very high. Forcing the garbage collector (via DDMS) reduces the 
allocated dalvik memory a little bit, but doesn't reduce the allocated native 
memory. One more iteration would cause an OutOfMemory exception. But when I 
wait some time (I tried about 30 seconds), the next iteration doesn't cause the 
exception, quite the contrary happens: the native memory is suddenly low again 
and I can do 5 more iterations without a problem!

That's very weird and I don't understand what's going on. I also don't 
understand why there are problems with MyLocationOverlay only.

I use other overlays as well: a PathOverlay, an ItemizedOverlayWithFocus, and a 
DirectedLocationOverlay. None of these overlays produce the memory problem, but 
since I don't understand the real cause of the problem, there may be more 
configurations wich cause the error.

I hope someone with a deeper insight into Osmdroid and the Android memory 
management can use this information to find the cause of the problem, because 
the OutOfMemory exception is really annoying.

Original comment by sepp.dot...@googlemail.com on 10 Feb 2011 at 2:08

GoogleCodeExporter commented 9 years ago
Thanks for those clear steps. I have at least added a catch in revision 789.

It's strange that MyLocationOverlay seems to be relevant.  I tried recycling 
the bitmaps in MyLocationOverlay.finalize() but then I got a real crash.

It's also interesting that it seems to settle down if you leave it for 30 
seconds. Hopefully that indicates that it won't be a problem in normal usage.

Original comment by neilboyd on 10 Feb 2011 at 4:15

GoogleCodeExporter commented 9 years ago
Unfortunately the patch did not work. I think that calling gc() does not help 
in this case. I already tried forcing the gc via the DDMS feature, without 
success.

Additionally, also the 30 seconds delay didn't help this time - I could only 
start the app 1 more time for each delay, and after the fifth time the app 
crashed.

This weird android memory management makes me crazy :-(

I don't know, but maybe calling the recycle method is the only thing which 
helps, because it really frees the native memory, but I don't know when and 
where.

Original comment by sepp.dot...@googlemail.com on 10 Feb 2011 at 5:30

GoogleCodeExporter commented 9 years ago
I've got it! It seems incredible, but it looks like that it is the Android 
LocatonManager which causes the problems! Maybe an Android bug?

Calling "LocationManager.removeUpdates(this)" only stops receiving new 
locations, but it seems not to remove the reference to the listener, so the 
MyLocationOverlay will not be purged.

I moved the location listener to a small helper class, which forwards location 
changes to the MyLocationOverlay object. Using this little modification allowed 
me to start the OpenStreetMapViewer sample more than 50 times without any 
problems. 

When disabling the listener, it is very important to remove any reference 
between the helper class and MyLocationOverlay. I have attached the helper 
class and the modified MyLocationOverlay class.

Original comment by sepp.dot...@googlemail.com on 11 Feb 2011 at 3:07

Attachments:

GoogleCodeExporter commented 9 years ago
That's great news! I'll have a look when I get time - probably next week.  
Sounds like something to be aware of in other apps too.

Original comment by neilboyd on 11 Feb 2011 at 4:11

GoogleCodeExporter commented 9 years ago
Implemented a slight variation of this patch in revision 805.

Original comment by neilboyd on 14 Feb 2011 at 1:26

GoogleCodeExporter commented 9 years ago
I have good and bad news - first the bad one: the OutOfMemoryException is back, 
you only need to enable the compass and show the map a few times.

Now the good one: the Android SensorManager seems to have the same problem as 
the LocationManager, so a similar simple workaround using a proxy class to 
register as a listener should help. I have not yet tried, but I am pretty sure 
that it will work.

Original comment by sepp.dot...@googlemail.com on 2 Mar 2011 at 8:51

GoogleCodeExporter commented 9 years ago
I've the the compass proxy in revision 841.

Original comment by neilboyd on 2 Mar 2011 at 9:17

GoogleCodeExporter commented 9 years ago

Hi Neil,
that was a really fast fix!

I tested the patch and it works :-)

Btw, during the tests I found a bug in the OpenStreetMapViewer sample: a call 
to disable the compass is missing in the method onPause(). But even after 
adding that statement, I got the OutOfMemoryException (without your patch, of 
course), but now I had to start the sample more often (about 30 times).

After applying the patch, I could start the sample more than 100 times, without 
any problems.

Then I tried the sample with your patch, but without disabling the compass. Now 
I had to start the sample for more than 50 times to get the 
OutOfMemoryException, probably because the proxy leaks less memory than 
MyLocationOverlay.

The patch works perferctly! Thank you for the fast fix!

Original comment by sepp.dot...@googlemail.com on 2 Mar 2011 at 10:32

GoogleCodeExporter commented 9 years ago
I added a call to disableCompass in revision 846.

I got a bit confused reading your last comment ;-)  Is it okay now?

Well done for your persistence in starting 100 times!  Did you just pause and 
start, or did you try other things as well, like rotating the screen and 
zooming and panning?

I don't think we're ever going to get rid of OOME altogether, but we can at 
least avoid wasting memory as much as possible, and handling it when it happens.

Original comment by neilboyd on 2 Mar 2011 at 10:59

GoogleCodeExporter commented 9 years ago
Sorry about my confusing comment - yes, it is okay now.
I just wanted to test each combination of disable the compass or not, and using 
the patch or not. As expected, you need both, disable the compass and use the 
proxy listener.

For the tests, I only started the app and waited until the compass was 
initialized and showed the correct direction. Sometimes I rotated the device a 
little bit, but I did no zoom and pan or other things.

Original comment by sepp.dot...@googlemail.com on 2 Mar 2011 at 12:22

GoogleCodeExporter commented 9 years ago
By the way, i have added a bug report to the Android bug tracker, it's issue 
1570
Link: http://code.google.com/p/android/issues/detail?id=15170

Original comment by sepp.dot...@googlemail.com on 2 Mar 2011 at 4:24

GoogleCodeExporter commented 9 years ago
This fix may have been broken in revision 848.

Original comment by neilboyd on 3 Mar 2011 at 2:55

GoogleCodeExporter commented 9 years ago
That broken code was fixed in revision 856. Now we can close this issue.

Any future OOME fixes can be submitted in a new issue.

Original comment by neilboyd on 4 Mar 2011 at 6:14