private OffHeapStoredObject allocateFromFragments(int chunkSize) {
    do {
      final int lastAllocationId = lastFragmentAllocation.get();
      for (int i = lastAllocationId; i < fragmentList.size(); i++) {
        OffHeapStoredObject result = allocateFromFragment(i, chunkSize);
        if (result != null) {
          return result;
        }
      }
      for (int i = 0; i < lastAllocationId; i++) {
        OffHeapStoredObject result = allocateFromFragment(i, chunkSize);
        if (result != null) {
          return result;
        }
      }
    } while (defragment(chunkSize));
    // We tried all the fragments and didn't find any free memory.
    logOffHeapState(chunkSize);
    final OutOfOffHeapMemoryException failure = new OutOfOffHeapMemoryException(
        "Out of off-heap memory. Could not allocate size of " + chunkSize);
    try {
      throw failure;
    } finally {
      ma.getOutOfOffHeapMemoryListener().outOfOffHeapMemory(failure);
    }
  }
Allocate a chunk of memory of at least the given size. The basic algorithm is: 1. Look for a
previously allocated and freed chunk close to the size requested. 2. See if the original chunk
is big enough to split. If so do so. 3. Look for a previously allocated and freed chunk of any
size larger than the one requested. If we find one split it.
<p>
It might be better not to include step 3 since we expect and freed chunk to be reallocated in
the future. Maybe it would be better for 3 to look for adjacent free blocks that can be merged
together. For now we will just try 1 and 2 and then report out of mem.

@param size minimum bytes the returned chunk must have.
@return the allocated chunk
@throws IllegalStateException if a chunk can not be allocated.
geode-core/src/main/java/org/apache/geode/internal/offheap/FreeListManager.java