Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (524)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (592)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  java.lang.OutOfMemoryError: bitmap size exceeds VM budget  (Read 14525 times)
0 Members and 1 Guest are viewing this topic.
Offline strategy
« Posted 2010-03-29 10:12:46 »

Need to vent on the bane of all my Android code. Apart from one release that contained an unfortunate bug that I didn't catch, at least 80% of all the force closes I see are caused by the above error; the remaining force closes being almost always caused by code that has been implemented to prevent the above error.

Has anyone got some good tips on how to avoid this? Google's official stance seems to be "use smaller bitmaps" as well as denial of claims that Android leaks resources; in other words, no help at all. I know exactly the amount of graphics that should be loaded in memory and - it's large - but nowhere near 16mb. I can note down some of the steps that I've used that have reduced the problem a lot - though not eliminated it entirely.

- Large bitmaps loaded using Bitmap.Config.RGB_565 ( = smaller size).
- All the bitmaps loaded up front in a centralized ImageLibrary class. This ensures that no large bitmaps are loaded more than once, and that all the bitmaps are explicitly recycled and nulled when the application switches out.
- In general, the code is gone through with a fine tooth comb to prevent any form of memory leaks. Difficult to guarantee none, of course, but there is definitely no large scale mem leaks left.
- Explicit call of System.gc() when cleaning out/redrawing large bitmaps. Ugly and slow, but every little thing helps.
- Bitmapfactory.decodeResources (which has a reputation for memory leaks) is cleaned out of the code. Removing those calls seemed to reduce out of memory errors a good deal (though perhaps I am just imagining things). I am contemplating removing bitmaps out of the layouts as well now, as that is presumably the only place left where Bitmapfactory is being used.

Anyone knows of any tricks I've missed?


Offline i30817

Junior Devvie





« Reply #1 - Posted 2010-03-29 11:50:29 »

System.gc() is one of the first things i delete when i see it on a project.

Anyway guess the emulator has no memory profiler right?
Offline noblemaster

« JGO Spiffy Duke »


Medals: 20
Projects: 10


Age of Conquest makes your day!


« Reply #2 - Posted 2010-03-29 19:01:40 »

Yep, that's pretty much it. I didn't try Bitmap.Config.RGB_565. Does that really make a difference?

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline strategy
« Reply #3 - Posted 2010-03-29 20:18:43 »

I'm not using System.gc() because I like to do so. And I'm not even convinced it does much (as I understand it, bitmaps are treated specially in the VM). But every little bit helps, and my app doesn't require animation. Sad

It is possible to do memory profiling of the Android processes, but because of the aforementioned issue (i.e., special treatment for bitmaps), it's not really all that useful to solve this problem.

@kingaschi:
RGB_565 should pretty much halve the memory footprint of your bitmaps (16bit versus 32bit). As I recall, the logcat also confirmed that this was the case, so yes. Note though it does mean no transparency.

Offline teletubo
« League of Dukes »

JGO Ninja


Medals: 48
Projects: 4
Exp: 8 years



« Reply #4 - Posted 2010-03-29 21:20:41 »

I'm not using System.gc() because I like to do so. And I'm not even convinced it does much (as I understand it, bitmaps are treated specially in the VM). But every little bit helps, and my app doesn't require animation. Sad

It is possible to do memory profiling of the Android processes, but because of the aforementioned issue (i.e., special treatment for bitmaps), it's not really all that useful to solve this problem.

@kingaschi:
RGB_565 should pretty much halve the memory footprint of your bitmaps (16bit versus 32bit). As I recall, the logcat also confirmed that this was the case, so yes. Note though it does mean no transparency.

I don't think calling the System.gc() would help in this case . Before failing because a memory shortage, the GC will try to free some memory .
The System.gc() call is useful if you want to free up some memory before starting a new stage for example, to make sure it won't run in the middle of the action and slow things down .

But as for your problem, I really don't know what can help . I never ran into such problems in my games, but I never really used lots and lots of bitmaps . Maybe make sure everything that might refer to this bitmap is really gone ? (i.e. a Canvas)

Offline princec

« JGO Spiffy Duke »


Medals: 422
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #5 - Posted 2010-03-29 21:45:54 »

Is there no RGB4444?

Cas Smiley

Offline Karmington

Senior Devvie


Medals: 1
Projects: 1


Co-op Freak


« Reply #6 - Posted 2010-03-29 22:31:51 »

Show the freemem on screen live, and you might be wiser.

If you are 100% sure this is due to graphics only, one must try to split up bigger pieces into tilesets.
For one game we pretty much cut anything with a horizontal or vertical stretch into endbits and tiled 1px-wide middle strips
to eke out everything we could out of the Series40 mobile limits.

However, it seems you know how much graphics you have. And you have the profiler: if the profiler + gfx goes over your limit,
the problem is in the code after all perhaps?


Offline Abuse

JGO Knight


Medals: 14


falling into the abyss of reality


« Reply #7 - Posted 2010-03-30 00:21:49 »

Are you loading the images in order of size (largest first)?
If the memory occupied by the images is being flagged as unmovable for gc purposes this should reduce the impact of the fragmentation.

Back in the day this is an issue that many of the more frustrating J2ME phones suffered from (predominantly Motorolas); though by now I would hope Android phones would be more sophisticated.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline ctrl-alt-dev

Senior Newbie




Today, my bedroom. Tomorrow the World !


« Reply #8 - Posted 2010-03-30 05:34:31 »

Have you tried using SoftReferences for referencing the bitmaps?

This way the GC should clear out references  before you run out of memory.
Combined with a lazy loading mechanism this will give you more memory to work with, at the expense of more IO and decoding ofcourse.  Smiley

http://developer.android.com/reference/java/lang/ref/SoftReference.html
Offline strategy
« Reply #9 - Posted 2010-03-30 20:26:35 »

@princec: There is indeed an RGB_4444 that could also be used.  Smiley

@Karmington: It's (fairly) easy to see how much memory is being used by the android program itself. In my case, it is nowhere near the limit and there is no memory leak apparent at all in the main code itself. There might be a memory leak in my use of bitmap though I would be rather surprised if there was, considering the number of times I've gone over that code to recycle and null everything. It's not that big and complex a program.

The problem is rather obfuscated (as no one seems to be able to find the exact issue); but the best "explanation" I've read yet suggests that the problem in Android is that the Dalvik VM doesn't keep track of the native heap (which is where bitmaps are stored) and doesn't garbage collect there. The result being that bitmap data that has actually been recycled/deleted in the VM may linger for awhile before it is garbage collected by whatever process administrates the native heap. Unfortunately I've yet to see Google even acknowledge that there is a problem.

@Abuse: Yep.

@C-A-D: Unfortunately, the way I use graphics, that method really shouldn't work (I already purge graphics aggressively once they are no longer needed). Might be worth experimenting with it though...

Thanks for all the suggestions and thoughts.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline DzzD
« Reply #10 - Posted 2010-03-30 22:49:58 »

maybe you could try to make a "test prog" that load and free a lot of bitmap to validate or invalidate that possible VM memory bug ? 

Offline strategy
« Reply #11 - Posted 2010-03-30 23:10:48 »

maybe you could try to make a "test prog" that load and free a lot of bitmap to validate or invalidate that possible VM memory bug ? 

The problem has been discussed a number of times on the android lists/forums, so I don't think there is much question that there is a bug. It's easy enough to provoke if you load one or two large bitmaps and do something like deallocating/reallocating the resources in onPause/onResume. Doing all the stuff I mentioned above helps reduce the problem to some extent, but doesn't solve it entirely.

Offline OverKill

Junior Devvie




Java games rock!


« Reply #12 - Posted 2010-03-31 07:25:40 »

System.gc() is one of the first things i delete when i see it on a project.

Anyway guess the emulator has no memory profiler right?
Actually I'd say it should be tested with and without.
If it works better with, then leave it in.
Why?
While I have no experience with Android I do have a lot with j2me mobiles and in some cases it could actually help.
Along with other crazy/strange stuff (f.i. after 'loading' a resource, a s.o.p with the handle would assure it is fully loaded)
Don't ask me why, it just did.
Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #13 - Posted 2010-05-18 20:02:50 »

Quote
The problem has been discussed a number of times on the android lists/forums, so I don't think there is much question that there is a bug.

Perhaps not, but a bug report with a small test case usually go a long way in making sure a problem is getting fixed.

Offline EgonOlsen
« Reply #14 - Posted 2010-05-29 06:28:18 »

- Bitmapfactory.decodeResources (which has a reputation for memory leaks) is cleaned out of the code.
What are you using instead now?

Offline strategy
« Reply #15 - Posted 2010-05-30 18:28:01 »

I load the drawable and then draw it to an empty bitmap. Fairly similar to what Robert Green does in this code snippet.

Note that many of the worst issues seem to have been fixed with OS 2.1 - I note, for instance, that the case where an extended View (one can make a very basic extends of View to demonstrate it) leaks when switching between ContentViews in the same activity is no longer a problem in 2.1 (below 2.1, though, you get orphaned objects). Without having dug into it in detail (which - as mentioned - is very difficult, as we don't have access to the bitmap heap), the resource handling seems to work better on 2.1 - though perhaps I'm just seeing the consequence of general bug fixes to the framework like the stuff mentioned above.

Offline EgonOlsen
« Reply #16 - Posted 2010-05-31 17:30:12 »

I load the drawable and then draw it to an empty bitmap. Fairly similar to what Robert Green does in this code snippet.
Thanks, i'll play around with that to see if it helps.

Offline strategy
« Reply #17 - Posted 2010-05-31 23:14:05 »

An important recommendation (if you haven't already done this), is to take a heap dump of your app after operating it for some length of time, and running it through the memory analyzer, looking for duplicates objects (especially your own). Because of all the callbacks in the Android GUI code, it is actually fairly easy to leak GUI objects - and that can quickly eat up mem.

Offline EgonOlsen
« Reply #18 - Posted 2010-06-01 10:49:40 »

Actually, it's an application with a deterministic behaviour and memory consumption. It starts at A) and runs over B) and C) to D), where it exits. It's a benchmark (this one: http://www.jpct.net/jpct-ae/download/alpha/bench/Benchmark-AE.apk). It's memory consumption shouldn't exceed 7+mb. However, from time to time, it's unable to create some Bitmaps even if it's nowhere near 16mb. This isn't a huge problem because it happens very seldom and maybe only on my phone (Galaxy, Android 1.5), but i would like to see this fixed anyway. The change from BitmapFactory to Drawable didn't do any good. It's nice to have the option anyway...

Offline strategy
« Reply #19 - Posted 2010-06-01 14:30:07 »

The benchmark functions very modestly for most of the benchmark (3-6Mb of heap on the 1.5 emulator), but when you hit the last part of the benchmark (Game Level), I'm registering heap usage of between 14000 - 17000 kb (using procrank). With that kind of resource usage, you shouldn't be surprised if it crashes out of memory every now and then as that doesn't give you a a lot of leeway.

On a hdpi 2.2 emulator it peaks at around 19mb, which gives you a little more than 4mb of heap space.

Offline EgonOlsen
« Reply #20 - Posted 2010-06-01 20:31:27 »

Thanks for pointing out the high memory consumption when loading the game level...this version of the benchmark was accidentally using the wrong model (well, actually it's the correct model, but i used the one serialized for the desktop version of jPCT, which was overkill for Android). I've fixed this, memory usage should be much lower now.
However, that's not the real problem, because i never got any crashes while loading the level but only when loading the textures (which happens before loading the level itself) and while showing the result screen. In both cases, memory is pretty empty...maybe 2.5 MB are in use then...but it still couldn't create those bitmaps/dialog box for whatever reason from time to time.

Offline strategy
« Reply #21 - Posted 2010-06-02 08:37:52 »

Hmm. Well, unfortunately I don't have the answers on this. I've succeeded to a large extent with eliminating OOM errors on my apps by a strict regime of trimming the graphics, going banzai on memory leaks, and strictly controlling the graphics in memory as mentioned above (having one module that controls all the graphics loading/cleaning is probably the key for me - once everything is loaded once, the apps memory usage remains stable).

Regarding your memory usage of 2.5mb - that sounds very low for the amount of graphics you are using. Are you sure that you are seeing the memory usage including bitmaps (you need to run "adb shell procrank" - heap dumps won't give you this information)?

The native heap GC is extremely slow, so I suppose that it is not impossible that you could be getting inside its GC cycle if you are loading/cleaning out bitmaps rapidly enough (as I suggets above). However, I've (fortunately) yet to find a problem that suggests it is a real issue - the problems I've traced down have ultimately all been down to memory leaks somewhere in either my own or Google's code - and the stuff that I know of in the Android OS has been fixed in the latest OS versions.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

toopeicgaming1999 (66 views)
2014-11-26 15:22:04

toopeicgaming1999 (58 views)
2014-11-26 15:20:36

toopeicgaming1999 (12 views)
2014-11-26 15:20:08

SHC (24 views)
2014-11-25 12:00:59

SHC (24 views)
2014-11-25 11:53:45

Norakomi (28 views)
2014-11-25 11:26:43

Gibbo3771 (24 views)
2014-11-24 19:59:16

trollwarrior1 (37 views)
2014-11-22 12:13:56

xFryIx (76 views)
2014-11-13 12:34:49

digdugdiggy (53 views)
2014-11-12 21:11:50
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!