I think it's better to add a couple more columns to the table to see the
picture (as I see it) more clearly:
JH = Java Heap
JU = Memory actually used by Java
NH = Native Heap
TU = Total memory Used = JU + NH
TA = Total memory Allocated = JH + NH

(note I'm not distinguishing between native heap and native heap used
because it's not relevant here)

The system requires TA (the process size as you called it) to not exceed
16MB, the evolution is:

    JU JH NH TU TA
 1)  2  2  0  2  2
 2)  4  4  0  4  4
 3)  4  4  2  6  6
 4) 14 14 2 16 16
 5)  4 14  2  6 16
 6)  4 14  4 10 18 *** OH NO! ***

The key is what happens between (4) and (5): GC reclaims 10MB (JU reduced by
10MB) but the java heap doesn't shrink (JH stays at 14MB). This enlarged
java heap basically squeezes the maximum native heap allocation.

The simplest approach is to try and ensure that your application maintains a
'flatish' memory profile - no big spikes. You should do this anyway, since
it means that your application is being well behaved and won't force other
apps to be terminated just because your application needs a temporary shot
of memory (which will then remain as a glut until the application restarts).

As you point out, WebViews are heavy on memory usage, and these might be
what's causing your memory usage to spike. I don't have any good suggestions
for a fix. You might try to pre-allocate bitmap memory before launching the
WebViews? It might work, but it may be complicated to do and could cause
OOMs when WebViews are instantiated - no way around that, your application
is simply using too much memory at that point.

Tom

2009/10/7 Mariano Kamp <mariano.k...@gmail.com>

> Hi Tom, thanks for taking the time.
>
> On Wed, Oct 7, 2009 at 8:34 PM, Tom Gibara <m...@tomgibara.com> wrote:
>
>>  1) Process starts up, generating a java heap allocation of 2MB.
>>  2) Application initializes its state and allocates 2MB in the java heap.
>>  3) Application creates a 2MB Bitmap which is allocated in the native heap
>>  4) Application updates its state by crunching a 10MB byte array
>>  5) Garbage collector kicks in and reclaims the 10MB byte array
>>  6) Application attempts to a create a new 2MB Bitmap
>>  7) An OutOfMemoryException is raised.
>>
>
> For the slow learners, like me:
>
> After Step) Java Heap, Native Heap, Process Size
> 1) 2, 0, 2
> 2) 4, 0, 4
> 3) 4, 2, 6
> 4) 14, 2, 16 (no the process is at its limit)
> 5) 4, 2, 16
> 6) Bang, because Native Heap needs to be grown by 2 MB, but the Process
> Size reached its 16MB ceiling in step 4.
> Is that it?
>
> And the Native Heap is in the same process as the Java Heap? I thought
> before that the bitmaps reside in another process and my process is just
> used for "accounting".
>
> Any good way to work around this? It doesn't happen all that often, but
> two, three times a week I need to send an apology to users where this
> happened? Either I have to automate the apology (a popup maybe?) or I can
> fix the issue. But the latter doesn't seem that easy. For some sites WebView
> really takes a lot of memory and I won't be able to "fix" that. And afaik I
> can't signal the OS to please restart my process or can I?
>
> Cheers,
> Mariano
>
>
>
>
>> At first sight it looks as though the total memory usage at (6) is 6MB
>> (4MB java and 2MB native) so the allocation should succeed. BUT (4) raised
>> the Java heap size to 14MB, and though most of that is no longer in use, the
>> java heap does not shrink. So the actual allocation to the native heap is
>> only 2MB and that is already used by the first bitmap.
>>
>> I hope this is correct, perhaps someone else could corroborate it, I don't
>> want to spread my misunderstandings.
>>
>> Tom
>>
>>
>> 2009/10/7 Mariano Kamp <mariano.k...@gmail.com>
>>
>> Hi,
>>>
>>>   I very often get bug reports about out-of-memory errors.
>>>
>>>   Those errors are caught bei the default exception handler where I then
>>> ask how much memory is left (see below). Very often, like in the case from
>>> below, there is plenty of memory left though.
>>>
>>>   I am wondering why this is?
>>> Of course, it might be that the bitmap (bitmap size exceeds VM budget) is
>>> actually megabytes and megabytes, but as these are resources that are small
>>> (and used by all the other users that don't get ooms) I would say that's not
>>> the case.
>>> Maybe the memory has been freed between the error and the measurement.
>>> That would be unfortunate. Any better wetter to measure the current memory
>>> consumption?
>>>
>>>   Or am I missing something and there is a completely different
>>> explanation? That would be wonderful and maybe give me a completely new
>>> attack vector against those bugs.
>>>
>>>   FWIW. I embed WebView and it is one of my top candidates for huge
>>> memory consumption. Maybe there is something I can measure?
>>>
>>> Cheers,
>>> Mariano
>>>
>>> -- Time: Sat Oct 03 11:19:00 GMT+01:00 2009
>>> -- Android Version: sdk=3, release=1.5, inc=150879
>>> -- Memory free: 12.27MB total: 15.44MB max: 16.00MB
>>> -- NewsRob Version: 3.1.0/310
>>> -- Stacktrace:(3390)
>>> android.view.InflateException: Binary XML file line #29: Error inflating
>>> class java.lang.reflect.Constructor
>>> at android.view.LayoutInflater.
>>>
>>> createView(LayoutInflater.java:512)
>>> at
>>> com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
>>> at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:562)
>>> at android.view.LayoutInflater.rInflate(LayoutInflater.java:617)
>>> at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
>>> at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
>>> at
>>> android.widget.ResourceCursorAdapter.newView(ResourceCursorAdapter.java:79)
>>> at
>>> android.widget.SimpleCursorAdapter.newView(SimpleCursorAdapter.java:93)
>>> at android.widget.CursorAdapter.getView(CursorAdapter.java:182)
>>> at android.widget.AbsListView.obtainView(AbsListView.java:1269)
>>> at android.widget.ListView.makeAndAddView(ListView.java:1623)
>>> at android.widget.ListView.fillDown(ListView.java:607)
>>> at android.widget.ListView.fillSpecific(ListView.java:1194)
>>> at android.widget.ListView.layoutChildren(ListView.java:1459)
>>> at android.widget.AbsListView.onLayout(AbsListView.java:1113)
>>> at android.view.View.layout(View.java:6133)
>>> at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
>>> at android.view.View.layout(View.java:6133)
>>> at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
>>> at android.view.View.layout(View.java:6133)
>>> at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
>>> at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)
>>> at android.widget.LinearLayout.onLayout(LinearLayout.java:918)
>>> at android.view.View.layout(View.java:6133)
>>> at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
>>> at android.view.View.layout(View.java:6133)
>>> at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
>>> at android.view.View.layout(View.java:6133)
>>> at android.view.ViewRoot.performTraversals(ViewRoot.java:929)
>>> at android.view.ViewRoot.handleMessage(ViewRoot.java:1482)
>>> at android.os.Handler.dispatchMessage(Handler.java:99)
>>> at android.os.Looper.loop(Looper.java:123)
>>> at android.app.ActivityThread.main(ActivityThread.java:3948)
>>> at java.lang.reflect.Method.invokeNative(Native Method)
>>> at java.lang.reflect.Method.invoke(Method.java:521)
>>> at
>>> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
>>> at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
>>> at dalvik.system.NativeStart.main(Native Method)
>>> Caused by: java.lang.reflect.InvocationTargetException
>>> at android.widget.TextView.<init>(TextView.java:308)
>>> at java.lang.reflect.Constructor.constructNative(Native Method)
>>> at java.lang.reflect.Constructor.newInstance(Constructor.java:446)
>>> at android.view.LayoutInflater.createView(LayoutInflater.java:499)
>>> ... 37 more
>>> Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
>>> at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
>>> at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:363)
>>> at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:212)
>>> at
>>> android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:663)
>>> at android.content.res.Resources.loadDrawable(Resources.java:1637)
>>> at android.content.res.TypedArray.getDrawable(TypedArray.java:548)
>>> at android.view.View.<init>(View.java:1725)
>>> at android.widget.TextView.<init>(TextView.java:314)
>>> ... 41 more
>>>
>>>
>>>
>>
>>
>>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to