OOM errors during inflation

by Ward Willats » Wed, 01 Apr 2009 05:48:08 GMT


Sponsored Links
 All of sudden I am seeing oddball OMM errors when inflating view trees.

The allocations are from really small (couple of K) to fairly large 
(couple of hundered K).

But ddms says the heap is only half full and there's around 2MB 
available. The app does not appear to be leaking.

What should I be checking?

Thanks all,

-- Ward

--~--~---------~--~----~------------~-------~--~----~



OOM errors during inflation

by Ward Willats » Sat, 04 Apr 2009 05:22:56 GMT


 Okay, starting to debug this by printing out Runtime() memory stats 
around setContentView(). There is less memory available than ddms 
says (500K vs 1.5 MB). So maybe it is really running out.

Are there any tools besides ddms to look at the heap? My app is using 
over 2 MB just sitting there -- and the ddms "track allocations" 
don't add up to near that amount. How can I get a good picture of 
what is going on in heapville?

-- Ward




--~--~---------~--~----~------------~-------~--~----~


Sponsored Links


OOM errors during inflation

by fadden » Sat, 04 Apr 2009 07:22:05 GMT


 


If you're on the emulator (or have root access on your device), you
can create a heap dump.  Some info here:

  



OOM errors during inflation

by Ward Willats » Wed, 08 Apr 2009 01:41:03 GMT


 I got a dump and jhat working -- thanks for the tip fadden. But I 
still don't see any monster allocations or leaks. This trace just 
came in:

04-07 10:06:56.341 D/ActivityBase(  820): setContentView(v) aft 
memory: T:5767 - F:1167 (KB)

...(do some work, but certainly don't do any any monster allocations) ...

04-07 10:06:59.101 E/dalvikvm-heap(  820): 26840-byte external 
allocation too large for this process.
04-07 10:06:59.101 E/        (  820): VM won't let us allocate 26840 bytes
04-07 10:06:59.161 D/AndroidRuntime(  820): Shutting down VM
04-07 10:06:59.161 W/dalvikvm(  820): threadid=3: thread exitin


According to System.freeMemory I have 1.1 MB of heap right after 
setContentView(), and yet I can't allocate a lousy 26K 4 seconds 
later.

Puzzling.



>



OOM errors during inflation

by Dianne Hackborn » Wed, 08 Apr 2009 03:35:47 GMT


 You probably have large bitmaps or a lot of bitmaps, whose allocation I
believe does not show up in hat.  (Note that I am pretty sure the error
message you are seeing is in fact due to a failing bitmap allocation.)





> 



OOM errors during inflation

by Ward Willats » Wed, 08 Apr 2009 05:04:05 GMT


 Thanks, Diane. Yes, a lot of little bitmaps -- and yes, it usually is 
a bitmap allocation failure.

What is the right way to figure their memory use?

(I mean, if I make a really small 4 bit indexed color png (no alpha) 
does it get "blown up" to RGB_888 or ARGB in the view buffers before 
being composited and handed to frame buffer memory?)

And 9 patches...can I get their RAM consumption by taking their final 
dimensions, and?

If you rotate the screen, do two copies of the view hierarchy exist 
for a moment?

Just trying to understand the machinery so I can attack this better...

-- Ward





>><



OOM errors during inflation

by Dianne Hackborn » Wed, 08 Apr 2009 06:39:53 GMT


 




They will generally either be loaded to 16bpp if there is no alpha channel,
or 32bpp is there is an alpha channel.




Yes, 9-patches are basically just bitmaps.




There is certainly a chance this can happen, though generally the first
activity is destroyed before the second is created (but any lingering
reference on any of the objects in the first activity can cause it to stay
around until that ref goes away).  Those won't duplicate bitmaps, though,
unless you are loading them yourself.

-- 
Dianne Hackborn
Android framework engineer
hack...@android.com

Note: please don't send private questions to me, as I don't have time to
provide private support, and so won't reply to such e-mails.  All such
questions should be posted on public forums, where I and others can see and
answer them.

--~--~---------~--~----~------------~-------~--~----~



OOM errors during inflation

by Ward Willats » Wed, 08 Apr 2009 23:28:14 GMT


 This is useful info for me, and I hope others. Sorry to be a pest but 
another question(s) for Those Who Know:

If you do a (nested) series of startActivtyForResult() (say 2-3) is 
the view hierarchy of the parent held in memory (yes, I think).

If so, would a good strategy be to setContentView( null ) in onStop() 
of the invoker and put it back onStart() ? (At the expense of UI 
performance.)

(Of course, I guess the right thing is to re-architect to not do this 
in the first place!)


On another topic, does Resources flush its cache in low-memory conditions?

-- Ward



--~--~---------~--~----~------------~-------~--~----~



OOM errors during inflation

by Dianne Hackborn » Thu, 09 Apr 2009 00:59:23 GMT


 




Yes.




If you really have a huge amount of data associated with the view hierarchy,
yeah you can do that...   however (1) there is no guarantee about the
timeliness of onStop() (just some time after the next activity is started)
so this means the app can probably be stressed into running out of memory,
and (2) generally it is better to just release whatever big resources that
you hold rather than throwing away the entire hierarchy.




That would be good. :)




The cache uses weak references, so unused resources are removed after every
gc.

-- 
Dianne Hackborn
Android framework engineer
hack...@android.com

Note: please don't send private questions to me, as I don't have time to
provide private support, and so won't reply to such e-mails.  All such
questions should be posted on public forums, where I and others can see and
answer them.

--~--~---------~--~----~------------~-------~--~----~



OOM errors during inflation

by Niek » Fri, 10 Apr 2009 01:44:56 GMT


 i guys,

I've read several posts from developers having OutOfMemory issues, and
a lot of them seem to be related to lists. I'm having a similar issue,
and the root of the problem seems to be a memory leak in the inflation
process.

The problem is particularly tricky to track down, because as of yet it
seems impossible to get a view of part of the heap (where the bitmaps
reside, and possibly other objects), as also mentioned by Ward and
others.

I created a small demo, so hopefully some Google engineers (Romain,
Dianne) can look at this, and either point out to me what I'm doing
wrong, or fix a possible memory leak in the inflation process in the
Android framework. I'm sure a lot of people would be very thankful if
this issue got resolved, as it often results in sudden crashes of the
app, without a clear reason. I must say it's disappointing to read the
standard: "use less memory" reply from Google to a lot of these posts,
as it seems to be worthy of further investigation.

Here's the demo, and the resulting logcat log with some peculiarities
contained within.

http://www.coffeebreakmedia.com/android_heap_issue.zip

A small explanation: it's a very simple list implementation with a
ListAdapter. It works fine if the list rows are inflated just once (by
re-using the convertView), but I purposely commented out two lines of
code:

// if(convertView == null) {
convertView = inflater.inflate(R.layout.list_row,
parent, false);
// }

This is to ensure that for each row, the XML is inflated again. In
this demo, this would be completely unnecessary and a big waste, but
in a real life a similar scenario happens when you have a list with a
few different types of rows (e.g., a different xml is used for the
header of a set of items, which use their own xml). In that case,
sometimes the convertView will be of the wrong type, in which case you
have to inflate another one. Obviously, this would then happen less
often than in this demo, but this only postpones the issue: eventually
you'll run into the same problem as is demonstrated here.

To test the demo, simply open the project in Eclipse (you can use the
emulator, but it also happens on the G1), and follow these
instructions:

1. Completely scroll down the list as fast as you can (all the way to
Item 199), and then back up again.
2. Keep doing this until you scrolled down & up about 5 times, while
watching the LogCat.

Eventually, you'll start getting errors such as these:

04-08 12:15:03.380: ERROR/dalvikvm-heap(345): 13824-byte external
allocation too large for this process.
04-08 12:15:03.380: ERROR/(345): VM won't let us allocate 13824 bytes

Keep scrolling! And you'll see this after a few more ups & downs:

04-08 12:16:48.589: DEBUG/dalvikvm(345): GC freed 0 objects / 0 bytes
in 169ms
04-08 12:16:48.589: INFO/dalvikvm-heap(345): Clamp target GC heap from
16.003MB to 16.000MB
04-08 12:16:48.589: INFO/dalvikvm-heap(345): Grow heap (frag case) to
16.000MB for 24-byte allocation
04-08 12:16:48.810: INFO/dalvikvm-heap(345): Clamp target GC heap from
18.003MB to 16.000MB

Apparently, the 16MB heap is used completely at this point, which
seems rather wasteful considering the simplicity of the application in
question.

After still more scrolling, you'll get errors such as this:

04-08 12:17:01.700: ERROR/dalvikvm-heap(345): Out of memory on a 708-
byte alloca



OOM errors during inflation

by Romain Guy » Fri, 10 Apr 2009 02:44:47 GMT


 here is no memory leak in LayoutInflater. While this is never a
proof, it's something we never encountered in
any of the apps we wrote. Also, the Android team works very hard to
plug all the memory leaks we can find
and when we tell developers to use less memory it's when we're pretty
sure that the APIs that seem to be
causing the memory leak are not responsible.

For instance, in your case you are basically saying that if you
inflate views until you run out of memory, you
run out of memory. Every View created by the adapter is kept by the
ListView in a 'recycler'. That recycler is
used to provide the adapter with a convertView whenever possible. That
means you MUST reuse the
convertView.

If you need views of different types in the list, just use the
appropriate APIs: Adapter.getViewTypeCount() and
Adapter.getItemViewType(int position) (see
http://d.android.com/reference/android/widget/Adapter.html). If
you implement these methods correctly, ListView will manage several
recyclers and always give you back the
correct convertView.

On Wed, Apr 8, 2009 at 6:14 AM, Niek <niekvansuchte...@gmail.com> wrote:



--
Romain Guy
Android framework engineer
romain...@android.com

Note: please don't send private questions to me, as I don't have time
to provide private support. All such questions should be posted on
public forums, where I and others can see and answer them

--~--~---------~--~----~------------~-------~--~----~



OOM errors during inflation

by Niek » Fri, 10 Apr 2009 06:39:32 GMT


 i Romain,

Thanks a lot for your answer: this should definitely help fix the
issue! In fact, I
wouldn't be surprised if a lot of posts regarding OutOfMemory issues
are caused by
the same problem.

However, I think many hours of bug hunting could have been prevented
if this
'recycler' point was mentioned in the API docs for Adapter. My own
thinking was that
"convertView" was basically the View that was previously generated
(for the item
above the current one in the list), and if you wouldn't use it, it
would be garbage
collected.

Take the following from getView:

"convertView - The old view to reuse, if possible. Note: You should
check that this
view is non-null and of an appropriate type before using. If it is not
possible to
convert this view to display the correct data, this method can create
a new view."

It actually talks about "this method can create a new view", but to me
it's not clear
that a reference to each returned View is kept somewhere in the
ListView. How could I
have known this? You may have written part of this code, so it's
probably very
obvious to you, but to the outside developer, it's not.

The point about how you MUST reuse the convertView should be stressed
much more
clearly in the API docs, in my opinion. As well as the point about the
recycler.
Alternatively, maybe the Adapter implementation could be changed so
that it always
only keeps one reference of a particular type of View. Why should it
keep multiple
references to the same View type, if it's only possible to provide a
single one as
convertView?

Either way, I'm very happy to finally understand the inner workings of
the Adapter,
and it will help create more robust code.

Kind regards,
- Niek

<i posted this msg in Issue 2391 as well: my original msg here took
over 24 hours to get posted due to moderation>

On Apr 9, 8:44pm, Romain Guy <romain...@google.com> wrote:
--~--~---------~--~----~------------~-------~--~----~



Other Threads

1. "CREATE TABLE android_metadata failed"

Hi All,

         I am using SDK1.0 version. I am using database for storing
business card type information. Every thing was running fairly well.
All of a sudden I started getting following exception .

                      CREATE TABLE android_metadata failed

E/Database(  479): Failed to setLocale() when constructing, closing
the database
E/Database(  479): android.database.sqlite.SQLiteException: file is
encrypted or is not a database
E/Database(  479):      at
android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
E/Database(  479):      at
android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:
1470)
E/Database(  479):      at
android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:
1424)
E/Database(  479):      at
android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:
537)
E/Database(  479):      at
android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:
558)
E/Database(  479):      at
android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:
551)
E/Database(  479):      at
android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:
427)
E/Database(  479):      at
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:
98)
E/Database(  479):      at org.now.dd.db.now.<init>(now.java:121)
E/Database(  479):      at
org.now.dd.helpers.ServiceHelper.getSecurityTokenData(ServiceHelper.java:
967)
E/Database(  479):      at
org.now.dd.activities.Splash.populateIntentExtras(Splash.java:154)
E/Database(  479):      at
org.now.dd.activities.Splash.launchHome(Splash.java:133)
E/Database(  479):      at org.now.dd.activities.Splash
$1.run(Splash.java:65)
E/Database(  479):      at
android.os.Handler.handleCallback(Handler.java:542)
E/Database(  479):      at
android.os.Handler.dispatchMessage(Handler.java:86)
E/Database(  479):      at android.os.Looper.loop(Looper.java:123)
E/Database(  479):      at
android.app.ActivityThread.main(ActivityThread.java:3742)
E/Database(  479):      at
java.lang.reflect.Method.invokeNative(Native Method)
E/Database(  479):      at java.lang.reflect.Method.invoke(Method.java:
515)
E/Database(  479):      at com.android.internal.os.ZygoteInit
$MethodAndArgsCaller.run(ZygoteInit.java:739)
E/Database(  479):      at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
E/Database(  479):      at dalvik.system.NativeStart.main(Native
Method)
E/now(  479): Had an issue opening up the now Database
W/System.err(  479): android.database.sqlite.SQLiteException: file is
encrypted or is not a database
W/System.err(  479):    at
android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
W/System.err(  479):    at
android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:
1470)
W/System.err(  479):    at
android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:
1424)
W/System.err(  479):    at
android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:
537)
W/System.err(  479):    at
android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:
558)
W/System.err(  479):    at
android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:
551)
W/System.err(  479):    at
android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:
427)
W/System.err(  479):    at
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:
98)
W/System.err(  479):    at org.now.dd.db.now.<init>(now.java:121)
W/System.err(  479):    at
org.now.now.helpers.ServiceHelper.getSecurityTokenData(ServiceHelper.java:
967)
W/System.err(  479):    at
org.now.dd.activities.Splash.populateIntentExtras(Splash.java:154)
W/System.err(  479):    at
org.now.dd.activities.Splash.launchHome(Splash.java:133)
W/System.err(  479):    at org.new.dd.activities.Splash
$1.run(Splash.java:65)
W/System.err(  479):    at
android.os.Handler.handleCallback(Handler.java:542)
W/System.err(  479):    at
android.os.Handler.dispatchMessage(Handler.java:86)
W/System.err(  479):    at android.os.Looper.loop(Looper.java:123)
W/System.err(  479):    at
android.app.ActivityThread.main(ActivityThread.java:3742)
W/System.err(  479):    at
java.lang.reflect.Method.invokeNative(Native Method)
W/System.err(  479):    at java.lang.reflect.Method.invoke(Method.java:
515)
W/System.err(  479):    at com.android.internal.os.ZygoteInit
$MethodAndArgsCaller.run(ZygoteInit.java:739)
W/System.err(  479):    at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
W/System.err(  479):    at dalvik.system.NativeStart.main(Native
Method)


Has anyone ever dealt with a Problem where, Database developer is not
able to open created database?


Thanks
Amit Chabra





--~--~---------~--~----~------------~-------~--~----~

2. Convert a view (layout) to a Bitmap

Hello everybody.

I am working with OpenGL and Android, and I was wondering if there is
any way to create a Bitmap or a Drawable using a view (layout). The
purpose is to use this Bitmap as Texture for an OpenGL figure.

All I have untill now is:

** I create a new view from the context and the Id.

View l = new View(context);

l.findViewById(R.layout.main);

** I used DrawingCache...but dont know if it is well used:

l.setDrawingCacheEnabled(true);

Bitmap bmp = l.getDrawingCache();

this bmp is null...


Any idea?

Thanks
--~--~---------~--~----~------------~-------~--~----~

3. Strange WIFI behavior when the G1 screen is blacked/locked (sleeping ?).

4. How to set default contact phone number?

5. Handle events

6. OpenGL Hardware Acceleration in G1

7. Strange WIFI behavior when the G1 screen is blacked/locked (sleeping ?).