React-native: OutOfMemoryError in react-native 0.25

Created on 7 Jun 2016  路  18Comments  路  Source: facebook/react-native

java.lang.OutOfMemoryError: Failed to allocate a 10969356 byte allocation with 8599832 free bytes and 8MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:812)
at android.graphics.Bitmap.createBitmap(Bitmap.java:789)
at android.graphics.Bitmap.createBitmap(Bitmap.java:756)
at com.facebook.imagepipeline.memory.BitmapPool.alloc(BitmapPool.java:55)
at com.facebook.imagepipeline.memory.BitmapPool.alloc(BitmapPool.java:30)
at com.facebook.imagepipeline.memory.BasePool.get(BasePool.java:259)
at com.facebook.imagepipeline.platform.ArtDecoder.decodeStaticImageFromStream(ArtDecoder.java:137)
at com.facebook.imagepipeline.platform.ArtDecoder.decodeFromEncodedImage(ArtDecoder.java:81)
at com.facebook.imagepipeline.decoder.ImageDecoder.decodeStaticImage(ImageDecoder.java:127)
at com.facebook.imagepipeline.decoder.ImageDecoder.decodeImage(ImageDecoder.java:94)
at com.facebook.imagepipeline.producers.DecodeProducer$ProgressiveDecoder.doDecode(DecodeProducer.java:188)
at com.facebook.imagepipeline.producers.DecodeProducer$ProgressiveDecoder.access$200(DecodeProducer.java:96)
at com.facebook.imagepipeline.producers.DecodeProducer$ProgressiveDecoder$1.run(DecodeProducer.java:128)
at com.facebook.imagepipeline.producers.JobScheduler.doJob(JobScheduler.java:207)
at com.facebook.imagepipeline.producers.JobScheduler.access$000(JobScheduler.java:27)
at com.facebook.imagepipeline.producers.JobScheduler$1.run(JobScheduler.java:78)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at com.facebook.imagepipeline.core.PriorityThreadFactory$1.run(PriorityThreadFactory.java:43)
at java.lang.Thread.run(Thread.java:818)

version:
"iflux-native": "^1.0.6",
"immutable": "^3.7.4",
"moment": "^2.10.6",
"object-assign": "^4.0.1",
"querystring": "^0.2.0",
"react": "^0.14.8",
"react-mixin": "^2.0.2",
"react-native": "0.25.1",
"react-native-barcodescanner": "^1.0.1",
"react-native-camera": "git+https://github.com/lwansbrough/react-native-camera.git",
"react-native-circular-progress": "0.0.5",
"react-native-code-push": "^1.7.3-beta",
"react-native-htmlview": "0.4.2",
"react-native-viewpager": "git+http://git.dev.qianmi.com/OF730/react-native-viewpager.git",
"react-timer-mixin": "^0.13.3",
"url": "^0.11.0"

Locked

Most helpful comment

@huitsing it is still present with RN - 0.50.4

All 18 comments

It seems to me that it is a device problem...

The device doesn't have enough memory to handle whatever you are doing. (Treating an image I guess?).

We have the same problem on an old Android 4.4 device.

I'm not sure we can do anything about it, except optimize the treatment of the image.

Any Java wizard to do that ?

@wv1124 we have the same issue even on rn 0.28.0. seems to be a memory issue with the native android view pager. we get this when we do a lot of swiping in the view pager after 20 times the app crashes. On devices with less memory it crashes after 8 swipes. we moved to pure javascript implementation. Now it doesn't crash but it doesn't feel super native.

+1. We get this too, only on Android with RN 0.29.0.

Our app uses lots of photos. Eventually, if we click around, view peoples' profiles, close out the view, view someone else, over and over, we get OOM crash.

We have tried all the obvious stuff (android:largeHeap="true", making sure we load small/compressed images, etc). It seems like the images loaded via the components are never getting fully cleaned up. I've even gone so far as to make sure that the RN core android code is calling .close() on the Fresco image (it seems to be doing it in src/main/java/com/facebook/react/modules/image/ImageLoaderModule.java:132,:141 ). Sort of out of ideas! Basically, if you keep browsing around, opening and closing things, etc, you eventually OOM error and crash on Android (not on iOS).

What is most likely happening is that you have images that haven't been removed from the view hierarchy, even if you can't see them. Often, this is because something in your app that needs to be treated like a ListView: what I mean by that is that if you have some UI where the user can scroll through items, sending them offscreen, then those offscreen views need to be unmounted temporarily until they come back on screen. This is especially important for images because if we think the image might appear back on screen soon we won't deallocate the bitmap from memory (and bitmaps are especially large).

If you're using our ViewPager, unfortunately it doesn't have great support for infinite scrolling. See https://github.com/facebook/react-native/blob/b0c023c85c9a1c675b6787c6292400c5fd229181/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java#L41-L49, there was apparently some incompatibility with the system ViewPager and the way we do layout which is keeping us from detaching children. I don't think this is a reasonable solution, but it's also not currently on our roadmap. If you want to try to fix it, you can get detaching behavior by removing the setOffscreenPageLimit calls and trying to see if you can debug the layout problems that were apparently happening.

If you're not using ViewPager, try to verify that you see image views being unmounted in your app (the lines you're pointing out @huitsing are related to closing the network request and not actually removing the image from the view hierarchy).

@astreet This also happens when reloading a bundle in dev mode. Probably images don't get cleared up when bridge gets destroyed?

That's possible, we'd need to do a memory analysis: could be other things that are not properly being released as well/instead.

Hi @astreet - We'll triple verify that the components are being unmounted properly (also, we're not using ViewPager). We don't think this is the problem, however. Wondering if it's related to facebook/fresco#1363, or some other reason the images aren't properly freed even after their component unmounts.

That could definitely be the case, though I don't think we actually require the finalizer to be called to drop the bitmap from memory: that should happen when the image is detached from the view hierarchy. e.g., you should see https://github.com/facebook/fresco/blob/4b94f604e0a98a999dcc1357992f8cb34b1b83b6/drawee/src/main/java/com/facebook/drawee/view/DraweeView.java#L173 when you unmount the view if things are working properly.

Yes, @astreet is correct - Fresco uses deterministic memory management so it is not dependent on the finalizers. The problem is probably with the integration somewhere - someone from the Fresco team will look into this this week.

Thanks @astreet and @balazsbalazs. You are both correct - we've run the app with memory profiling, and we do see large amounts of memory being both allocated and also released as we navigate around the app viewing photos. So for sure, in general, the image content is being freed successfully very quickly after the view containing the image content is closed.

Our problem must be more subtle. We've spent some time reducing image sizes, unmounting views more aggressively, etc, and are feeling much more comfortable about the memory usage. We've still can produce OOM errors, but they are infrequent and require long sessions within the app. I appreciate the tips of things to look into so far!

I'd be very interested to hear what you find out. What top level native components are you using? ScrollView, ViewPager, something custom? I ask since the other major thing I'd look for is not dropping Views (another large object, though not as large as images generally): this could either be a bug in the framework, though I'm not aware of anyone else hitting one besides the ViewPager one I mentioned above, or something to do with a custom viewmanager.

We have heavy use of <Image />, and then we use <Modal /> <Navigator /> <View /> <ScrollView >, etc. We'll for-sure follow up if we find a smoking gun, and we'll look forward to any other activity around memory management.

Hi there,

I'm experiencing common OOM errors in my RN app. Currently it's basically a ListVIew with images loaded from the device storage and you can tap on any to see it full screen. I'm using a library react-native-transformable-image on top so that images can be zoomed and panned. They are loaded in their biggest size.

The thing, is that I end up with a Fatal Exception: java.lang.OutOfMemoryError because the app fails to allocate memory in the heap.

captura de pantalla 2016-09-05 a las 12 29 08

I've decided to track memory heap in my RN app and I can see how the app heap size gets slowly bigger and bigger until it collapses.

captura de pantalla 2016-09-05 a las 12 30 48

The images I'm loading are taken using the device camera in highest resolution available, in my Nexus 5X this results in pretty big images. If I use the allocation tracker, I can see how fresco imagepipeline JpegTranscoder is behind the biggest size chunks.

captura de pantalla 2016-09-05 a las 12 32 27

When I unload my full screen image detail, i can see how some memory heap is released, but I would say not all of it. I have the feeling that there is a memory leak somewhere, I have checked my RN app and i don't think it's in my JS code. If I downscale the image quality or size, the problem is still there although you simply need a longer session to crash the app.

This is happening in RN 0.30. is there anything I can send or do to fix this issue ?

Thanks

Just giving an update to this older issue:

We don't struggle with this problem too much any more. We've reduced the size of images loaded, turned on large heap, etc, and OOM crashes are no longer at the top of our list with more recent versions of React Native.

Closing this issue because it has been inactive for a while. If you think it should still be opened let us know why.

@hramos
It still happens in 1.5.0. Following is the error log. Even if it is the problem of device, please do not throw this OOM error since I cannot catch it.

java.lang.OutOfMemoryError: Failed to allocate a 8294412 byte allocation with 1121032 free bytes and 1094KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:843)
at android.graphics.Bitmap.createBitmap(Bitmap.java:820)
at android.graphics.Bitmap.createBitmap(Bitmap.java:787)
at com.facebook.imagepipeline.memory.BitmapPool.alloc(BitmapPool.java:53)
at com.facebook.imagepipeline.memory.BitmapPool.alloc(BitmapPool.java:28)
at com.facebook.imagepipeline.memory.BasePool.get(BasePool.java:257)
at com.facebook.imagepipeline.platform.ArtDecoder.decodeStaticImageFromStream(ArtDecoder.java:134)
at com.facebook.imagepipeline.platform.ArtDecoder.decodeJPEGFromEncodedImage(ArtDecoder.java:117)
at com.facebook.imagepipeline.decoder.DefaultImageDecoder.decodeJpeg(DefaultImageDecoder.java:184)
at com.facebook.imagepipeline.decoder.DefaultImageDecoder$1.decode(DefaultImageDecoder.java:59)
at com.facebook.imagepipeline.decoder.DefaultImageDecoder.decode(DefaultImageDecoder.java:122)
at com.facebook.imagepipeline.producers.DecodeProducer$ProgressiveDecoder.doDecode(DecodeProducer.java:245)
at com.facebook.imagepipeline.producers.DecodeProducer$ProgressiveDecoder.access$200(DecodeProducer.java:109)
at com.facebook.imagepipeline.producers.DecodeProducer$ProgressiveDecoder$1.run(DecodeProducer.java:142)
at com.facebook.imagepipeline.producers.JobScheduler.doJob(JobScheduler.java:204)
at com.facebook.imagepipeline.producers.JobScheduler.access$000(JobScheduler.java:24)
at com.facebook.imagepipeline.producers.JobScheduler$1.run(JobScheduler.java:75)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at com.facebook.imagepipeline.core.PriorityThreadFactory$1.run(PriorityThreadFactory.java:42)
at java.lang.Thread.run(Thread.java:818)

@huitsing it is still present with RN - 0.50.4

it is still present

Was this page helpful?
0 / 5 - 0 ratings