Fast erase (not clear) a ByteBuffer in Java
Have you tried using one of the ByteBuffer.put(byte[])
or ByteBuffer.put(ByteBuffer)
methods to write multiple zeros in one go? You could then iterate over the buffer in chunks of 100 or 1000 bytes, or whatever, using an array or buffer pre-filled with zeros.
Downside: this is an optional operation, so not all implementations of ByteBuffer are required to provide it...
If you need a fresh clean zero-filled ByteBuffer
after the hash table is flushed, the easiest way is to drop the existing ByteBuffer
and allocate a new one. The official documentation does not say so, but all known implementations zero the memory of new buffers. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542 for additional info.
As DNA mentions, having a pre-filled buffer and using ByteBuffer.put(ByteBuffer)
is probably the fastest portable way. If that's not practical, you can do something like this to take advantage of either Arrays.fill
or Unsafe.putLong
when applicable:
public static void fill(ByteBuffer buf, byte b) {
if (buf.hasArray()) {
final int offset = buf.arrayOffset();
Arrays.fill(buf.array(), offset + buf.position(), offset + buf.limit(), b);
buf.position(buf.limit());
} else {
int remaining = buf.remaining();
if (UNALIGNED_ACCESS) {
final int i = (b << 24) | (b << 16) | (b << 8) | b;
final long l = ((long) i << 32) | i;
while (remaining >= 8) {
buf.putLong(l);
remaining -= 8;
}
}
while (remaining-- > 0) {
buf.put(b);
}
}
}
Setting UNALIGNED_ACCESS
requires some knowledge of your JRE implementation and platform. Here's how I would set it for the Oracle JRE when also using JNA (which provides Platform.ARCH
as a convenient, canonical way to access the os.arch
system property).
/**
* Indicates whether the ByteBuffer implementation likely supports unaligned
* access of multi-byte values on the current platform.
*/
private static final boolean UNALIGNED_ACCESS = Platform.ARCH.startsWith("x86");
For ByteBuffer
implementations that provide the optional array()
method (where hasArray()
returns true
), you could use this method get a reference to the underlying array, then use java.util.Arrays#fill()
.