docs: @VisibleForTesting
    void trimToNothing() {
      final List<Bucket<V>> bucketsToTrim;
  
      synchronized (this) {
        if (mPoolParams.fixBucketsReinitialization) {
          bucketsToTrim = refillBuckets();
        } else {
          bucketsToTrim = new ArrayList<>(mBuckets.size());
          final SparseIntArray inUseCounts = new SparseIntArray();
  
          for (int i = 0; i < mBuckets.size(); ++i) {
            final Bucket<V> bucket = mBuckets.valueAt(i);
            if (bucket.getFreeListSize() > 0) {
              bucketsToTrim.add(bucket);
            }
            inUseCounts.put(mBuckets.keyAt(i), bucket.getInUseCount());
          }
  
          legacyInitBuckets(inUseCounts);
        }
  
        // free up the stats
        mFree.reset();
        logStats();
      }
  
      // the pool parameters 'may' have changed.
      onParamsChanged();
  
      // Explicitly free all the values.
      // All the core data structures have now been reset. We no longer need to block other calls.
      // This is true even for a concurrent trim() call
      for (int i = 0; i < bucketsToTrim.size(); ++i) {
        final Bucket<V> bucket = bucketsToTrim.get(i);
        while (true) {
          // what happens if we run into an exception during the recycle. I'm going to ignore
          // these exceptions for now, and let the GC handle the rest of the to-be-recycled-bitmaps
          // in its usual fashion
          V item = bucket.pop();
          if (item == null) {
            break;
          }
          free(item);
        }
      }
    }