Closed GoogleCodeExporter closed 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
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
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
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
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
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:
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
Implemented a slight variation of this patch in revision 805.
Original comment by neilboyd
on 14 Feb 2011 at 1:26
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
I've the the compass proxy in revision 841.
Original comment by neilboyd
on 2 Mar 2011 at 9:17
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
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
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
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
This fix may have been broken in revision 848.
Original comment by neilboyd
on 3 Mar 2011 at 2:55
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
Original issue reported on code.google.com by
ti...@ametov.net
on 6 Feb 2011 at 12:59