question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Xamarin.Forms - Android] Java.Lang.OutOfMemoryError after loading multiple pages with multiple images

See original GitHub issue

Description

Multiple Java.Lang.OutOfMemoryError until the app crashes when loading multiple pages with multiple images. It occurs only on Android, and it seems to concern “older” devices or those who less power, less memory.

Steps to Reproduce

Xamarin Forms app with a main tabbed page. There are 3 pages with one listview in each (each listview is paged, so I use an infinite scroll implementation and use a CacheStrategy = RecycleElement). All listview items contain a small avatar pics loaded with FFImageLoading, and one of these listview displays also one big picture in each item, loaded with FFImageLoading.

All pages load correctly, and display pics. But after navigating between each page, and scroll on some, I got multiple Java.Lang.OutOfMemoryError until the app crashes. If I don’t use FFImageLoading, the problem does not occur but the app becomes slower. It only occurs on Android devices.

Avatar size is approximately 300 to 500 ko. And big pics size is 500 to 1 Mo.

Expected Behavior

No error, and at least the memory and the GC be cleaned.

Actual Behavior

App crashes after loading approximately 50 pics between multiple pages.

XAML

Partial XAML of the ListView ViewCell with avatar and big pics:

<ViewCell BindingContextChanged="Handle_BindingContextChanged">
<!-- other XAML parts -->
<ffimageloading:CachedImage WidthRequest="55" HeightRequest="55" DownsampleToViewSize="true" DownsampleWidth="55" DownsampleHeight="55" ErrorPlaceholder="error.png" LoadingPlaceholder="loading.gif" Aspect="AspectFill" x:Name="PostCreatorImage" Grid.Column="0" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand">
                                            <ffimageloading:CachedImage.Transformations>
                                                <fftransformations:CircleTransformation />
                                            </ffimageloading:CachedImage.Transformations>
                                            <ffimageloading:CachedImage.GestureRecognizers>
                                                <TapGestureRecognizer Command="{Binding OpenUserProfileCommand}" />
                                            </ffimageloading:CachedImage.GestureRecognizers>
                                        </ffimageloading:CachedImage>
<!-- other XAML parts -->
<ffimageloading:CachedImage x:Name="PostAssetImage" Grid.Row="1" DownsampleToViewSize="true" DownsampleHeight="400" ErrorPlaceholder="error.png" LoadingPlaceholder="loading.gif" MinimumHeightRequest="300" HeightRequest="400" IsVisible="{Binding HasAssets}" Margin="-10, 0" Aspect="AspectFill">
                                                <ffimageloading:CachedImage.GestureRecognizers>
                                                    <TapGestureRecognizer Command="{Binding OpenAssetsCommand}" />
                                                </ffimageloading:CachedImage.GestureRecognizers>
                                            </ffimageloading:CachedImage>
<!-- other XAML parts -->
</ViewCell>

I tried to set only DownsampleToViewSize or only DownsampleHeight/DownsampleWidth ; I tried to add TransformPlaceholders=“false” and FadeAnimations=“false” but no change.

XAML behind code

As you suggested, I load pic with manual set during the OnBindingContextChanged of ViewCell

void Handle_BindingContextChanged(object sender, System.EventArgs e)
{
      var cell = sender as ViewCell;
      var postViewModel = cell?.BindingContext as PostViewModel;

      if (postViewModel == null)
           return;

      var creatorImage = cell.FindByName<CachedImage>("PostCreatorImage");
      if (creatorImage == null)
           return;

      creatorImage.Source = postViewModel.Post?.CreatorUser?.ThumbnailAvatarUrl;

      var cachedImage = cell.FindByName<CachedImage>("PostAssetImage");
      if (cachedImage == null)
           return;

      cachedImage.Source = postViewModel.Asset?.ThumbnailUrl;

      base.OnBindingContextChanged();
}

I tried to implement my own CacheKeyFactory. It seemed to be a little bit more efficient but the problem still occurs after.

Android MainActivity and MainApplication

In MainActivity, and in MainApplication, I override OnTrimMemory and OnLowMemory, but when I debug on physical device, it never stops on my breakpoint so it seems these methods are never call:

public override void OnTrimMemory(TrimMemory level)
{
      FFImageLoading.ImageService.Instance.InvalidateMemoryCache();
      GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
      base.OnTrimMemory(level);
}

public override void OnLowMemory()
{
       FFImageLoading.ImageService.Instance.InvalidateMemoryCache();
       GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
       base.OnLowMemory();
}

In the App.cs, I tried to set these properties (because I saw you did it in your samples, but I don’t know what are use for):

FFImageLoading.Forms.CachedImage.FixedOnMeasureBehavior = true;
FFImageLoading.Forms.CachedImage.FixedAndroidMotionEventHandler = true;

Logs

First loads when everything is right:
[AbsListView] viewType is heaer or footer
[art] Starting a blocking GC Explicit
[Mono] GC_BRIDGE waiting for bridge processing to finish
[art] Explicit concurrent mark sweep GC freed 987(74KB) AllocSpace objects, 2(2MB) LOS objects, 22% free, 56MB/72MB, paused 683us total 27.404ms
[Mono] GC_TAR_BRIDGE bridges 294 objects 347 opaque 13 colors 294 colors-bridged 294 colors-visible 294 xref 10 cache-hit 0 cache-semihit 0 cache-miss 0 setup 0.12ms tarjan 0.42ms scc-setup 0.15ms gather-xref 0.02ms xref-setup 0.02ms cleanup 0.11ms
[Mono] GC_BRIDGE: Complete, was running for 33.09ms
[Mono] GC_MAJOR: (LOS overflow) time 37.74ms, stw 38.63ms los size: 4552K in use: 3436K
[Mono] GC_MAJOR_SWEEP: major size: 4368K in use: 3100K
Thread finished:  #12
[AbsListView] viewType is heaer or footer
[art] Starting a blocking GC Explicit
[art] Explicit concurrent mark sweep GC freed 18(1376B) AllocSpace objects, 3(7MB) LOS objects, 17% free, 73MB/89MB, paused 664us total 27.451ms
[Mono] GC_TAR_BRIDGE bridges 278 objects 332 opaque 15 colors 278 colors-bridged 278 colors-visible 278 xref 11 cache-hit 0 cache-semihit 0 cache-miss 0 setup 0.12ms tarjan 0.34ms scc-setup 0.17ms gather-xref 0.02ms xref-setup 0.02ms cleanup 0.08ms
[Mono] GC_BRIDGE: Complete, was running for 32.91ms
[Mono] GC_MAJOR: (LOS overflow) time 33.13ms, stw 33.89ms los size: 4552K in use: 3420K
[Mono] GC_MAJOR_SWEEP: major size: 4368K in use: 3085K
[ViewRootImpl] ViewPostImeInputStage processPointer 0
[TextView] setTypeface with style : 0
[TextView] setTypeface with style : 0
[TextView] setTypeface with style : 0
[ViewRootImpl] ViewPostImeInputStage processPointer 1
Thread started:  #14
[Mono] GC_BRIDGE waiting for bridge processing to finish
[art] Starting a blocking GC Explicit
[art] Explicit concurrent mark sweep GC freed 687(32KB) AllocSpace objects, 3(4MB) LOS objects, 13% free, 100MB/116MB, paused 778us total 29.272ms
[Mono] GC_TAR_BRIDGE bridges 377 objects 442 opaque 15 colors 377 colors-bridged 377 colors-visible 377 xref 11 cache-hit 0 cache-semihit 0 cache-miss 0 setup 0.12ms tarjan 0.52ms scc-setup 0.21ms gather-xref 0.02ms xref-setup 0.03ms cleanup 0.12ms
[Mono] GC_BRIDGE: Complete, was running for 36.25ms
[Mono] GC_MAJOR: (LOS overflow) time 44.17ms, stw 45.30ms los size: 4552K in use: 2687K
[Mono] GC_MAJOR_SWEEP: major size: 4496K in use: 3277K
[ViewRootImpl] ViewPostImeInputStage processPointer 0

And when errors occur:

[art] Alloc partial concurrent mark sweep GC freed 6(192B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 761us total 25.514ms
[art] Starting a blocking GC Alloc
[art] Clamp target GC heap from 271MB to 256MB
[art] Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 769us total 33.270ms
[art] Forcing collection of SoftReferences for 2MB allocation
[art] Starting a blocking GC Alloc
[art] Clamp target GC heap from 271MB to 256MB
[art] Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 762us total 33.492ms
[art] Throwing OutOfMemoryError "Failed to allocate a 2560012 byte allocation with 728824 free bytes and 711KB until OOM"
Setting placeholder failed
Java.Lang.OutOfMemoryError: Failed to allocate a 2560012 byte allocation with 728824 free bytes and 711KB until OOM
  at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00069] in <da9f450baed342f3af31c42cec968688>:0 
  at Java.Interop.JniPeerMembers+JniStaticMethods.InvokeObjectMethod (System.String encodedMember, Java.Interop.JniArgumentValue* parameters) [0x00018] in <da9f450baed342f3af31c42cec968688>:0 
  at Android.Graphics.Bitmap.CreateBitmap (System.Int32[] colors, System.Int32 width, System.Int32 height, Android.Graphics.Bitmap+Config config) [0x00077] in <5f142c269d8a438c94480ac03744dec7>:0 
  at FFImageLoading.Decoders.GifDecoder+PlatformGifHelper.ToBitmapAsync (System.Int32[] data, System.Int32 width, System.Int32 height, System.Int32 downsampleWidth, System.Int32 downsampleHeight) [0x00000] in C:\projects\ffimageloading\source\FFImageLoading.Droid\Decoders\GifDecoder.cs:57 
  at FFImageLoading.GifHelperBase`1+<SetPixelsAsync>d__54[TNativeImageContainer].MoveNext () [0x00276] in C:\projects\ffimageloading\source\FFImageLoading.Common\Helpers\GifHelperBase.cs:186 
--- End of stack trace from previous location where exception was thrown ---
  at FFImageLoading.GifHelperBase`1+<ReadBitmapAsync>d__67[TNativeImageContainer].MoveNext () [0x00284] in C:\projects\ffimageloading\source\FFImageLoading.Common\Helpers\GifHelperBase.cs:626 
--- End of stack trace from previous location where exception was thrown ---
  at FFImageLoading.GifHelperBase`1+<ReadContentsAsync>d__64[TNativeImageContainer].MoveNext () [0x00083] in C:\projects\ffimageloading\source\FFImageLoading.Common\Helpers\GifHelperBase.cs:494 
--- End of stack trace from previous location where exception was thrown ---
  at FFImageLoading.GifHelperBase`1+<ReadGifAsync>d__56[TNativeImageContainer].MoveNext () [0x00140] in C:\projects\ffimageloading\source\FFImageLoading.Common\Helpers\GifHelperBase.cs:252 
--- End of stack trace from previous location where exception was thrown ---
  at FFImageLoading.Decoders.GifDecoder+<DecodeAsync>d__0.MoveNext () [0x0004a] in C:\projects\ffimageloading\source\FFImageLoading.Droid\Decoders\GifDecoder.cs:19 
--- End of stack trace from previous location where exception was thrown ---
  at FFImageLoading.Work.ImageLoaderTask`3+<GenerateImageAsync>d__104[TDecoderContainer,TImageContainer,TImageView].MoveNext () [0x00072] in C:\projects\ffimageloading\source\FFImageLoading.Common\Work\ImageLoaderTask.cs:280 
--- End of stack trace from previous location where exception was thrown ---
  at FFImageLoading.Work.ImageLoaderTask`3+<ShowPlaceholder>d__108[TDecoderContainer,TImageContainer,TImageView].MoveNext () [0x0037e] in C:\projects\ffimageloading\source\FFImageLoading.Common\Work\ImageLoaderTask.cs:486 
  --- End of managed Java.Lang.OutOfMemoryError stack trace ---
java.lang.OutOfMemoryError: Failed to allocate a 2560012 byte allocation with 728824 free bytes and 711KB until OOM
	at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
	at android.graphics.Bitmap.nativeCreate(Native Method)
	at android.graphics.Bitmap.createBitmap(Bitmap.java:1048)
	at android.graphics.Bitmap.createBitmap(Bitmap.java:1072)

Basic Information

  • Version with issue: 2.4.5.860-pre
  • Last known good version: I don’t know, I discovered this error after publishing the app for the first time, and I didn’t get this on test devices who are recent and powerful (Samsung Galaxy S8)
  • Platform: Xamarin Forms 3.4.0.1009999 / Android (5.1.1, 6.0.1, 7.0 and 8.0)
  • Devices : Samsung Galaxy J3 (2016), A3 (2016), Honor 5C (2016), Motorola One Power (2017)

Your plugin is very good. And it works perfectly on iOS. This is my only problem to get a stable app. Hope someone will get an idea.

Thanks for your help !

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:2
  • Comments:10 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
plsgardcommented, Feb 15, 2019

I could not try on previous version of XF, but I tried by removing FFImageLoading on most of the pages and I did not get OOM anymore. I saw that the memory free space changes but it does not go to OOM.

I also realized that my avatar thumbnail size is big (1000x1000px) while I downsample to 55px or 45px on most of the pages. Maybe it requires to much memory to downsample, even if I also specify the WidthRequest and HeightRequest on the component.

@daniel-luberda, did I do something wrong ?

Thanks for your help

1reaction
plsgardcommented, Jan 24, 2019

Hi @plsgard, did you tried with a older version of X.F ?

Not exactly. I didn’t try recently with older version. I encountered a similar error few weeks ago on an older version of XF, but it appears on only one device, so I didn’t work on it at that moment. I’m gonna take a look when I can.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Xamarin bitmap out of memory - android
I don't bind them through code. After I move from one page to another several times, this exception appears. Xamarin caused by: java.lang....
Read more >
How to resolve out of memory exception when loading ...
Xamarin.Forms ... When you try to load large size images in image editor in Android, ... You can resolve this exception by using...
Read more >
Xamarin Android FIX error XA5213 java lang OutOfMemoryError
How to fix error XA5213 java lang OutOfMemoryError Websites https://www.paypal.me/jocheojeda https://www.facebook.com/xafes/ ...
Read more >
Xamarin.Forms Performance on Android
When adding this image handler to my sample, it both loads and scrolls blazingly fast. No out of memory errors--it just works. It...
Read more >
Loading Large Bitmaps Efficiently | App quality
This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found