NegativeArraySizeException in DiskBasedCache.streamToBytes

2,839 views
Skip to first unread message

Dongwon Shin

unread,
Jul 8, 2014, 4:43:22 AM7/8/14
to volley...@googlegroups.com
07-08 17:13:59.020: E/AndroidRuntime(751): FATAL EXCEPTION: Thread-13931
07-08 17:13:59.020: E/AndroidRuntime(751): Process: #######, PID: 751
07-08 17:13:59.020: E/AndroidRuntime(751): java.lang.NegativeArraySizeException: -535
07-08 17:13:59.020: E/AndroidRuntime(751):  at com.android.volley.toolbox.DiskBasedCache.streamToBytes(DiskBasedCache.java:316)
07-08 17:13:59.020: E/AndroidRuntime(751):  at com.android.volley.toolbox.DiskBasedCache.get(DiskBasedCache.java:117)
07-08 17:13:59.020: E/AndroidRuntime(751):  at com.android.volley.CacheDispatcher.run(CacheDispatcher.java:101)

it appears very rarely, but because of this my app crashes. 


mani s

unread,
Dec 3, 2014, 12:05:18 PM12/3/14
to volley...@googlegroups.com

I faced the same exception. The issue is when cache dispatcher tries to find if there is a cached response for a request, it check with DiskCache ( mCache) get(String key).

There is a parallelism happening that when cache dispatcher thread is executing get method of Diskcache, the cached file is deleted by the Android OS for clean up. As OS can delete cache files from cache directory to reclaim space. So after this line of execution 
'    cis = new CountingInputStream(new FileInputStream(file));' 

System has deleted the cache file. And in this line of exection 
'    byte[] data = streamToBytes(cis, (int) (file.length() - cis.bytesRead));'
file.length() results to be Zero. ( this doesn't throw IO Exception. Returns 0 if file is not present). So NegativeArraySizeException is thrown.

This can be fixed by adding a 
- catch (NegativeArraySizeException) block in addition to IOException. (Personally feel its better)
- or get the file length in a local variable ahead of 'streamToBytes' method. So if file is deleted due to parallelism by OS, we still have the right value to play with. And since file's stream is opened before we pass to 'streamToBytes' the contents of the file is cached in memory and we can safely read the content. 


public synchronized Entry get(String key) {
    CacheHeader entry = mEntries.get(key);
    // if the entry does not exist, return.
    if (entry == null) {
        return null;
    }

File file = getFileForKey(key);
CountingInputStream cis = null;
try {
    cis = new CountingInputStream(new FileInputStream(file));
    CacheHeader.readHeader(cis); // eat header
    byte[] data = streamToBytes(cis, (int) (file.length() - cis.bytesRead));
    return entry.toCacheEntry(data);
} catch (IOException e) {
    VolleyLog.d("%s: %s", file.getAbsolutePath(), e.toString());
    remove(key);
    return null;
} finally {
    if (cis != null) {
        try {
            cis.close();
        } catch (IOException ioe) {
            return null;

邱平

unread,
Jan 26, 2016, 1:43:39 AM1/26/16
to Volley Users
for the convenience of other developer who faced this issue. 

J.T.H.

unread,
Jun 22, 2016, 3:59:05 PM6/22/16
to Volley Users
Can't believe this isn't fixed in the official Google Volley. So my only options are to include the deprecated com.mcxiaoke.volley or include Volley in my project the old way as a project instead the "new" gradle 'com.android.volley:volley:1.0.0'?

Ficus Kirkpatrick

unread,
Jun 22, 2016, 5:04:06 PM6/22/16
to J.T.H., Volley Users
If nobody has sent a patch, then it's likely not going to have been merged.

--
You received this message because you are subscribed to the Google Groups "Volley Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to volley-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

J.T.H.

unread,
Jun 23, 2016, 12:31:53 PM6/23/16
to Volley Users
What did you do to fix, or what would you suggest to do to fix this issue in my app? 

Add Volley as a project and add the code:

}  catch (NegativeArraySizeException e) {
            VolleyLog.d("%s: %s"file.getAbsolutePath(), e.toString());
            remove(key);
            return null;
}

Thanks,
JTH

Ficus Kirkpatrick

unread,
Jun 23, 2016, 1:29:15 PM6/23/16
to J.T.H., Volley Users
I didn't fix it. If there is a bug I'd be happy to merge a change that fixes it through the normal AOSP contributions process.

Thiago Porciúncula

unread,
Aug 9, 2016, 2:23:22 PM8/9/16
to Volley Users, joseph....@gmail.com
Has this been fixed or is there a plan to fix it?

I noticed a fix was applied to mcxiaoke's mirror, but I don't see it in Volley's source code.

Thank you.

Joe Bowbeer

unread,
Oct 3, 2016, 10:26:54 PM10/3/16
to Volley Users
I think the same problem (reading the header) can also result in an OutOfMemoryError:

https://github.com/mcxiaoke/android-volley/issues/61

However, I don't know what this problem is...

Shen Lin

unread,
Dec 8, 2016, 10:14:25 PM12/8/16
to Volley Users, joseph....@gmail.com
I've already sent a patchset at https://android-review.googlesource.com/#/c/311964/ . Please review it.

在 2016年6月24日星期五 UTC+8上午1:29:15,Ficus Kirkpatrick写道:

Shen Lin

unread,
Dec 10, 2016, 12:10:14 PM12/10/16
to Volley Users, joseph....@gmail.com
Already fixed in official repository, see https://android-review.googlesource.com/#/c/311964/ for more information.

在 2016年8月10日星期三 UTC+8上午2:23:22,Thiago Porciúncula写道:
Reply all
Reply to author
Forward
0 new messages