The Mem Ops BytesAllocatorAutoDefrag class is capable of allocating smaller sections (blocks) of a bigger byte array. Thus, a single, big byte array can be instantiated, and allocated into smaller sections which can be used as if they were separate byte arrays. You just need to know the start offset of the byte array section you have been allocated, and it's length, and you are good to go.
When you are done using an allocated byte array section you must explicitly free it. When you free a byte
array section, the
BytesAllocatorAutoDefrag class will automatically defragment its
internal big byte array so the freed section is joined with adjacent free sections to form a larger free
section from which future sections can be allocated. This is how the
BytesAllocatorAutoDefrag is different from the
This short video explains how the allocation, deallocation and defragmentation works:
Create a BytesAllocatorAutoDefrag
To use the
BytesAllocatorAutoDefrag class you must first create an instance of it.
Here is an example of creating a
BytesAllocatorAutoDefrag allocator = new BytesAllocatorAutoDefrag(new byte[1024 * 1024]);
Notice that you have to pass the underlying byte array as parameter to the
BytesAllocatorAutoDefrag. It is this byte array which you can allocate smaller
sections (blocks) from. This way you will only ever have this underlying byte array allocated in
the JVM. Your memory consumption remains completely stable, and no garbage collection needs to take place.
Allocate a Block
In order to allocate a block (section) of bytes from the underlying byte array, you call the
allocate() method. Once allocated, no other
allocate() call can allocate the same
block until it has been freed. The
allocate() method returns the offset into the big, underlying
byte array where the allocated block starts. If no block could be allocated, -1 is returned. Here is
an example of allocating a block of 1024 bytes:
int offset = allocator.allocate(1024);
Getting a Reference to the Byte Array
You can get a reference to the underlying byte array via the
getData() method. Your allocated
block will reside at the returned offset inside this byte array. Here is how obtaining the byte array looks:
byte data = allocator.getData();
Accessing the Allocated Block
Once you have allocated a block of bytes from the
BytesAllocatorAutoDefrag you can access
it via the data array, from the offset returned by
allocate() and until
offset + length - 1.
Here is an example of accessing an allocated block of bytes from a
int blockLength = 1024; int offset = allocator.allocate(blockLength); byte data = allocator.getData(); data[offset] = 1; //first byte of block data[offset + blockLength -1] = 2; //last byte of block
Notice the two last lines of the example. These two lines access the first and last byte of the allocated block. You can access all bytes from the first byte to the last byte this way.
Free a Block
Once you are finished with a memory block you must free it again. You free it using the
free() method takes the start and end offset of the block to free.
Here is an example of allocating and freeing a byte block:
int offset = allocator.allocate(1024); allocator.free(offset, offset + 1024);
Free Part of a Block
BytesAllocatorAutoDefrag does not care what size of block you free. If you allocate
a block of 1024 bytes and write 512 bytes into it, you can free the other 512 bytes immediately.
Here is an example of freeing part of an allocated block:
int offset = allocator.allocate(1024); allocator.free(offset + 512, offset + 1024);
Full BytesAllocatorAutoDefrag Example
Here is a full example showing how to allocate and free a memory block from a Mem Ops
int offset = allocator.allocate(1024); byte data = allocator.getData(); data[offset] = 1; //first byte of block data[offset + blockLength -1] = 2; //last byte of block //do something more with written bytes. allocator.free(offset, offset + 1024);