google / volley

https://google.github.io/volley
Apache License 2.0
3.38k stars 754 forks source link

Fatal Exception: java.lang.OutOfMemoryError #215

Closed ram-wavity closed 6 years ago

ram-wavity commented 6 years ago

Hi Team,

My app is getting crashed in Android 5.1.1 version with below mentioned crash logs. It's working fine from Android 6.0 version and above. Here i am using Volley 1.1.1

  1. com.android.volley.toolbox.ByteArrayPool.getBuf (ByteArrayPool.java:101)
  2. com.android.volley.toolbox.DiskBasedCache.streamToBytes (DiskBasedCache.java:341)

Please suggest above issues.

jpd236 commented 6 years ago

A full stack trace (including the message) would be needed. I've given some thoughts on the first one that might be relevant at https://github.com/google/volley/issues/199 and https://github.com/google/volley/issues/155. The second one has explicit protections to prevent unexpectedly large allocations, which makes me think this is just an honest OOM issue rather than anything that Volley can possibly do anything about. The message would hopefully show the amount of memory that we're trying to allocate, which would help pin down whether this is a large allocation attempt or whether the app is just running out of memory overall, which isn't anything Volley can do much about.

ram-wavity commented 6 years ago

Thanks for reply @jpd236 .

Please check full stack trace. 1. Fatal Exception: java.lang.OutOfMemoryError Failed to allocate a 1257466 byte allocation with 33 free bytes and 33B until OOM

com.android.volley.toolbox.ByteArrayPool.getBuf (ByteArrayPool.java:101) com.android.volley.toolbox.PoolingByteArrayOutputStream.expand (PoolingByteArrayOutputStream.java:76) com.android.volley.toolbox.PoolingByteArrayOutputStream.write(PoolingByteArrayOutputStream.java:84) com.android.volley.toolbox.BasicNetwork.inputStreamToBytes (BasicNetwork.java:280) com.android.volley.toolbox.BasicNetwork.performRequest (BasicNetwork.java:152) com.android.volley.NetworkDispatcher.processRequest (NetworkDispatcher.java:120) com.android.volley.NetworkDispatcher.run (NetworkDispatcher.java:87) 2. Fatal Exception: java.lang.OutOfMemoryError Failed to allocate a 2329104 byte allocation with 911152 free bytes and 889KB until OOM

com.android.volley.toolbox.DiskBasedCache.streamToBytes (DiskBasedCache.java:341) com.android.volley.toolbox.DiskBasedCache.get (DiskBasedCache.java:131) com.android.volley.CacheDispatcher.processRequest (CacheDispatcher.java:133) com.android.volley.CacheDispatcher.processRequest (CacheDispatcher.java:119) com.android.volley.CacheDispatcher.run (CacheDispatcher.java:97) 3. Fatal Exception: java.lang.OutOfMemoryError Failed to allocate a 2329104 byte allocation with 910944 free bytes and 889KB until OOM

java.io.ByteArrayOutputStream.toByteArray (ByteArrayOutputStream.java:122) com.android.volley.toolbox.BasicNetwork.inputStreamToBytes (BasicNetwork.java:282) com.android.volley.toolbox.BasicNetwork.performRequest (BasicNetwork.java:152) com.android.volley.NetworkDispatcher.processRequest (NetworkDispatcher.java:120) com.android.volley.NetworkDispatcher.run (NetworkDispatcher.java:87)

Device Properties: Brand: LAVA Model: Iris Fuel F1 Orientation: Portrait RAM free: 1.05 GB Disk free: 1.11 GB Version: 5.1

How can i handle this crashing issue?

joebowbeer commented 6 years ago

DiskBasedCache.java:341 is the line that creates the byte array, after invalid sizes have been rejected. I suspect the memory is too fragmented, which is probably more likely on the older version of Android.

ram-wavity commented 6 years ago

RequestQueue.getCache().clear();

What happens? if i use above line in my code level. It will impact on app performance?

is it helpful to handle OutOfMemoryErrors?

jpd236 commented 6 years ago

In stack 1, you are truly out of memory - there are only 33 bytes free. Basically any allocation could fail at that point. Stacks 2 and 3 aren't quite as extreme as you have about 0.9Mb free, but you still have a problem trying to allocate 2.3Mb.

2.3Mb is a pretty large request size; Volley is really only built to handle requests of relatively small size, because it stores them in memory. (https://github.com/google/volley/wiki/Frequently-Asked-Questions#why-doesnt-volley-support-large-downloadsuploads). Device manufacturers decide how much RAM to grant each app on any particular device, and this number can be quite low. It might be fragmentation... or you might just be running out of memory, legitimately.

You should make sure you don't have any memory leaks within your app using a tool like LeakCanary; if you are truly down to 33 bytes free in some scenario then you are bumping up against the limit and Volley can't do anything about that. Beyond that, if you want to support devices like this, you will need to find a way to keep memory usage down, either by making these HTTP requests/responses smaller, or by moving to a different library that streams the data rather than trying to load it all in memory.

Clearing the cache would be unlikely to fix anything. If you are so memory constrained that you can't fit the cache data into disk, then you won't have the memory to store the response data when you subsequently make the request over the network.

As it stands I don't see an action that can be taken at the Volley level here. I don't think Volley is doing anything unreasonable here; the app is just out of memory, legitimately.