Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fatal Exception: java.lang.IllegalStateException: com.squareup.picasso.LruCache.sizeOf() is reporting inconsistent results! #1693

Closed
dennischen0 opened this issue Oct 25, 2017 · 3 comments

Comments

@dennischen0
Copy link

dennischen0 commented Oct 25, 2017

A lot of my users are getting the following error, and only on Android 8:

Fatal Exception: java.lang.IllegalStateException: com.squareup.picasso.LruCache.sizeOf() is reporting inconsistent results!
       at com.squareup.picasso.LruCache.trimToSize(LruCache.java:94)
       at com.squareup.picasso.LruCache.set(LruCache.java:84)
       at com.squareup.picasso.Dispatcher.performComplete(Dispatcher.java:370)
       at com.squareup.picasso.Dispatcher$DispatcherHandler.handleMessage(Dispatcher.java:502)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loop(Looper.java:164)
       at android.os.HandlerThread.run(HandlerThread.java:65)

I have no idea how to reproduce it and don't know what's causing the error.

@mhswtf
Copy link

mhswtf commented Jan 2, 2018

This has been an issue for me for some time now as well.
I tried to debug it, and have worked out what causes the issue.
The problem occurs when the LruCache maxSize is exceeded. The eviction loop in the trimToSize() method will run, but the size returned by Utils.getBitmapBytes(value) is always zero, so all values will be evicted, eventually causing the crash when the value map is empty.
The reason getBitmapBytes() returns zero, is because the following if clause was added to the android Bitmap class getByteCount() method in api 26:
if (mRecycled) { Log.w(TAG, "Called getByteCount() on a recycle()'d bitmap! " + "This is undefined behavior!"); return 0; }

The method looks like this in api 25:
public final int getByteCount() { // int result permits bitmaps up to 46,340 x 46,340 return getRowBytes() * getHeight(); }

Hope this helps. I would really appreciate a fix for this, as I am using Picasso through a third party dependancy, so I cannot really do anything to mitigate the problem, and I am fearing the day that the Samsung army starts updating to Android 8! :-)

Regards,
/Mikkel Schläger

@bqmackay
Copy link

bqmackay commented Jan 10, 2018

Thanks @mhswtf for the insight. I would think a quick fix would be in LruCache.set where it has the following if statement before calling trimToSize:

  @Override public void set(@NonNull String key, @NonNull Bitmap bitmap) {
    ...
    int addedSize = Utils.getBitmapBytes(bitmap);
    if (addedSize > maxSize) {
      return;
    }
    ... 
    trimToSize(maxSize);
  }

If we added another check for 'Bitmap.isRecycled' to the already existing if statement, then the function returns immediately without calling trimToSize. Since this is a bailing condition statement already, I would think that adding Bitmap.isRecycled to it wouldn't have any far reaching effects. Thoughts?

My only hesitation at this point is that I can't recreate the crash on an emulator and I don't have a physical phone running Android 8 to test on. Has anyone found a consistent way to recreate the crash (on either emulator or physical device)?

@JakeWharton
Copy link
Collaborator

Fix was merged. Thanks for the report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants