public BlockCache(BlurMetrics metrics, boolean directAllocation, long totalMemory, int slabSize, int blockSize) { _metrics = metrics; _numberOfBlocksPerSlab = slabSize / blockSize; int numberOfSlabs = (int) (totalMemory / slabSize); _slabs = new ByteBuffer[numberOfSlabs]; _locks = new BlockLocks[numberOfSlabs]; _lockCounters = new AtomicInteger[numberOfSlabs]; _maxEntries = (_numberOfBlocksPerSlab * numberOfSlabs) - 1; for (int i = 0; i < numberOfSlabs; i++) { if (directAllocation) { _slabs[i] = ByteBuffer.allocateDirect(_numberOfBlocksPerSlab * blockSize); } else { _slabs[i] = ByteBuffer.allocate(_numberOfBlocksPerSlab * blockSize); } _locks[i] = new BlockLocks(_numberOfBlocksPerSlab); _lockCounters[i] = new AtomicInteger(); } EvictionListener<BlockCacheKey, BlockCacheLocation> listener = new EvictionListener<BlockCacheKey, BlockCacheLocation>() { @Override public void onEviction(BlockCacheKey key, BlockCacheLocation location) { releaseLocation(location); } }; _cache = new ConcurrentLinkedHashMap.Builder<BlockCacheKey, BlockCacheLocation>().maximumWeightedCapacity(_maxEntries).listener(listener).build(); _blockSize = blockSize; }