Skip to content

Instantly share code, notes, and snippets.

@nitsanw
Last active July 28, 2021 17:59
Show Gist options
  • Save nitsanw/4373453 to your computer and use it in GitHub Desktop.
Save nitsanw/4373453 to your computer and use it in GitHub Desktop.
Aligning a byte buffer
private static final long addressOffset;
static {
try {
addressOffset = UnsafeAccess.unsafe.objectFieldOffset(Buffer.class.getDeclaredField("address"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static long getAddress(ByteBuffer buffy) {
// steal the value of address field from Buffer, holding the memory address for this ByteBuffer
return UnsafeAccess.unsafe.getLong(buffy, addressOffset);
}
public static ByteBuffer allocateAlignedByteBuffer(int capacity, long align) {
// Power of 2 --> single bit, none power of 2 alignments are not allowed.
if (Long.bitCount(align) != 1) {
throw new IllegalArgumentException("Alignment must be a power of 2");
}
// We over allocate by the alignment so we know we can have a large enough aligned
// block of memory to use. Also set order to native while we are here.
ByteBuffer buffy = ByteBuffer.allocateDirect((int) (capacity + align));
long address = getAddress(buffy);
// check if we got lucky and the address is already aligned
if ((address & (align - 1)) == 0) {
// set the new limit to intended capacity
buffy.limit(capacity);
// the slice is now an aligned buffer of the required capacity
return buffy.slice().order(ByteOrder.nativeOrder());
} else {
// we need to shift the start position to an aligned address --> address + (align - (address % align))
// the modulo replacement with the & trick is valid for power of 2 values only
int newPosition = (int) (align - (address & (align - 1)));
// change the position
buffy.position(newPosition);
int newLimit = newPosition + capacity;
// set the new limit to accomodate offset + intended capacity
buffy.limit(newLimit);
// the slice is now an aligned buffer of the required capacity
return buffy.slice().order(ByteOrder.nativeOrder());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment