Thanks for the detailed response Tom. I understand the cause now. > You might try to pre-allocate bitmap memory before launching the WebViews? It's not the WebView that's triggering the OOM, but some arbitrary other piece of code that needs memory that is not *there* anymore. Very often this is happening when starting a new activity.
Ok, I see, I have to start dealing with automating my apology. There is one more, small thing that I can do. I also do some downloading and XML parsing in the background at times. This only takes Java Heap (<3MB), but maybe I should move that stuff to a separate process. This may lower the chances of an OOM. I'll think about it, but with all the added complexity of inter process communication I am not sure I would want to go there. Anyway, thanks for sharing your insights. That was very helpful. On Wed, Oct 7, 2009 at 10:48 PM, Tom Gibara <[email protected]> wrote: > 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 <[email protected]> > >> Hi Tom, thanks for taking the time. >> >> On Wed, Oct 7, 2009 at 8:34 PM, Tom Gibara <[email protected]> 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 <[email protected]> >>> >>> 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 [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en -~----------~----~----~----~------~----~------~--~---

