Skip to main content

Android implementation - heap memory problem

7 replies [Last post]
klemensz
Offline
Joined: 2007-02-25
Points: 0

Hi,
I'm using Thorsten's LWUIT port for Android and constantly run out of memory with the 16 MB heap limitation of the emulator. I wonder if anybody else has experienced that and maybe overcome it. The problem seems to be with bitmap images that I need (map tiles). Keeping ten png images of size 256x256 px in the memory shouldn't be a problem, should it?

I also need to repaint (animate) the whole screen often - could that lead to a problem? I'll investigate more into that issue...

Thanks!

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Klemens

Hi Thorsten,

There's a subtle but fatal bug in this line:
BitmapFactory.class.getField("inPurgeable").set(opts, true);

It should be
BitmapFactory.Options.class.getField("inPurgeable").set(opts, true);
instead.

Thanks,
Klemens

On 14.03.2010 09:49, lwuit-users@mobileandembedded.org wrote:
> Hello Klemens,
> thank you very much for your reports and findings on this issue. I will have a look at your changes and the whole bitmap/inPurgable thing in the following days. I will also widen access to the default font height property.
> Best regards,
> Thorsten.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
For additional commands, e-mail: users-help@lwuit.dev.java.net

thorsten_s
Offline
Joined: 2008-08-15
Points: 0

Oh, thanks for pointing that out. I just changed it.
Regards,
Thorsten.

Klemens

Great!
The error message that I get is "java.lang.OutOfMemoryError: bitmap size
exceeds VM budget". This has been discussed a lot in forums etc. Here's
the blog post the lead me to the inPurgable option:
http://www.droidnova.com/2d-sprite-animation-in-android-addendum,505.html

Klemens

On 14.03.2010 09:49, lwuit-users@mobileandembedded.org wrote:
> Hello Klemens,
> thank you very much for your reports and findings on this issue. I will have a look at your changes and the whole bitmap/inPurgable thing in the following days. I will also widen access to the default font height property.
> Best regards,
> Thorsten.
> [Message sent by forum member 'thorsten_s' (contact@pader-sync.com)]
>
> http://forums.java.net/jive/thread.jspa?messageID=391749
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
For additional commands, e-mail: users-help@lwuit.dev.java.net

klemensz
Offline
Joined: 2007-02-25
Points: 0

A short follow up: What helped in the end (after long hours of tweaking here and there) was setting inPurgeable to true when creating Bitmaps. I had to extend the AndroidImplementation:
@Override
public Object createImage(InputStream i) throws IOException {
BitmapFactory.Options ops = new BitmapFactory.Options();
ops.inPurgeable = true;
return BitmapFactory.decodeStream(i, null, ops);
}

@Override
public Object createImage(byte[] bytes, int offset, int len) {
BitmapFactory.Options ops = new BitmapFactory.Options();
ops.inPurgeable = true;
return BitmapFactory.decodeByteArray(bytes, offset, len, ops);
}

Be aware that this option is only available in Android 1.6+. So far I noticed no negative side effects after setting this. Otherwise Android doesn't seem to release the memory even if the image is not referenced any more.

Another feature that seems to eat the bitmap memory is scaled background images, for example with Forms.

Another thing @Thorsten: I noticed that the small system font is too small for my taste. Maybe you can make defaultFontHeight protected so one can override and access it in the init/createFont methods?

thorsten_s
Offline
Joined: 2008-08-15
Points: 0

Hello Klemens,
thank you very much for your reports and findings on this issue. I will have a look at your changes and the whole bitmap/inPurgable thing in the following days. I will also widen access to the default font height property.
Best regards,
Thorsten.

vprise
Offline
Joined: 2003-11-07
Points: 0

Since Android supports reflection, you can probably support older versions of Android by leveraging it like this, I haven't tested this though...:
[code]
@Override
public Object createImage(InputStream i) throws IOException {
BitmapFactory.Options ops = new BitmapFactory.Options();
try {
Field f = ops.getClass().getField("inPurgeable");
f.setBoolean(ops, Boolean.TRUE);
} catch(Throwable t) {
t.printStackTrace();
}
return BitmapFactory.decodeStream(i, null, ops);
}

@Override
public Object createImage(byte[] bytes, int offset, int len) {
BitmapFactory.Options ops = new BitmapFactory.Options();
try {
Field f = ops.getClass().getField("inPurgeable");
f.setBoolean(ops, Boolean.TRUE);
} catch(Throwable t) {
t.printStackTrace();
}
return BitmapFactory.decodeByteArray(bytes, offset, len, ops);
}
[/code]

Klemens

Thanks! The problem is that without this option I will run into an
OutOfMemory pretty fast, at least on the emulator. So it looks bad for
<1.6. Maybe devices have more memory.

I suppose avoiding bitmap fonts is also a good idea on Android. That's
when you learn to value Series 60 devices ;)

On 15.03.2010 15:24, lwuit-users@mobileandembedded.org wrote:
> Since Android supports reflection, you can probably support older versions of Android by leveraging it like this, I haven't tested this though...:
> @Override
> public Object createImage(InputStream i) throws IOException {
> BitmapFactory.Options ops = new BitmapFactory.Options();
> try {
> Field f = ops.getClass().getField("inPurgeable");
> f.setBoolean(ops, Boolean.TRUE);
> } catch(Throwable t) {
> t.printStackTrace();
> }
> return BitmapFactory.decodeStream(i, null, ops);
> }
>
> @Override
> public Object createImage(byte[] bytes, int offset, int len) {
> BitmapFactory.Options ops = new BitmapFactory.Options();
> try {
> Field f = ops.getClass().getField("inPurgeable");
> f.setBoolean(ops, Boolean.TRUE);
> } catch(Throwable t) {
> t.printStackTrace();
> }
> return BitmapFactory.decodeByteArray(bytes, offset, len, ops);
> }
> [Message sent by forum member 'vprise' (shai@vprise.com)]
>
> http://forums.java.net/jive/thread.jspa?messageID=391946
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
For additional commands, e-mail: users-help@lwuit.dev.java.net