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;