MyCATApache/Mycat-Server · error · IllegalArgumentException
bufferSize must be a power of 2
Error message
bufferSize must be a power of 2
What it means
RingBuffer's constructor validates that the buffer size is at least 1 and exactly a power of 2. The power-of-2 requirement lets the buffer compute ring indices with a cheap bitmask (indexMask = bufferSize - 1) instead of a modulo operation. Any size that is not 2^n fails this check and the constructor throws IllegalArgumentException.
Solutions
- Round the requested size up to the next power of 2 before constructing (e.g. Integer.highestOneBit(size - 1) << 1).
- Use a known-good size like 1024, 4096, or 8192 in your configuration.
- Validate/normalize user-supplied buffer-size config at startup with a clear message.
- Ensure the size is at least 1 to avoid the related 'must not be less than 1' error.
Example fix
// before RingBuffer ring = new RingBuffer(1000); // after int size = 1000; int pow2 = Integer.highestOneBit(Math.max(1, size - 1)) << 1; RingBuffer ring = new RingBuffer(pow2); // 1024
Defensive patterns
Strategy: validation
Validate before calling
public static int toPow2(int size) {
if (size < 1) throw new IllegalArgumentException("bufferSize must be >= 1");
return Integer.bitCount(size) == 1 ? size : Integer.highestOneBit(size - 1) << 1;
}
// call: new RingBuffer(toPow2(requestedSize)); Type guard
public static boolean isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
} Try / catch
try {
ring = new RingBuffer(configuredSize);
} catch (IllegalArgumentException e) {
ring = new RingBuffer(Integer.highestOneBit(Math.max(1, configuredSize - 1)) << 1);
} Prevention
- Always derive capacity via Integer.highestOneBit/next power of 2 helpers
- Use standard sizes (1024, 4096, 8192) in configs
- Validate buffer-size config at startup, before constructing the buffer
When it happens
Trigger: Calling the RingBuffer constructor with bufferSize values such as 0, 3, 100, 1000, or any integer where Integer.bitCount(bufferSize) != 1 (e.g. RingBuffer ring = new RingBuffer(1000);).
Common situations: Developers pick a 'nice round' buffer size like 1000 or 5000 for throughput tuning, or pass a user-supplied config value without validating it, or pass 0/negative values derived from a misconfigured property.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- bufferSize must not be less than 1
- Initial capacity exceeds maximum capacity of
- Page size cannot exceed
- Both batchStartsAt and batchSize must be positive but got…
- Initial capacity must be greater than 0
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/1659d6c62d0f4947.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/memory/unsafe/ringbuffer/RingBuffer.java:51
BUFFER_PAD = 128 / scale;
REF_ARRAY_BASE = Platform.arrayBaseOffset(Object[].class) + (BUFFER_PAD << REF_ELEMENT_SHIFT);
}
private final long indexMask;
private final Object[] entries;
protected final int bufferSize;
protected final Sequencer sequencer;
public RingBuffer(EventFactory<E> eventFactory, Sequencer sequencer) {
this.sequencer = sequencer;
this.bufferSize = sequencer.getBufferSize();
//保证buffer大小不小于1
if (bufferSize < 1) {
throw new IllegalArgumentException("bufferSize must not be less than 1");
}
//保证buffer大小为2的n次方
if (Integer.bitCount(bufferSize) != 1) {
throw new IllegalArgumentException("bufferSize must be a power of 2");
}
//m % 2^n <=> m & (2^n - 1)
this.indexMask = bufferSize - 1;
/**
* 结构:缓存行填充,避免频繁访问的任一entry与另一被修改的无关变量写入同一缓存行
* --------------
* * 数组头 * BASE
* * Padding * 128字节
* * reference1 * SCALE
* * reference2 * SCALE
* * reference3 * SCALE
* ..........
* * Padding * 128字节
* --------------
*/
this.entries = new Object[sequencer.getBufferSize() + 2 * BUFFER_PAD];
//利用eventFactory初始化RingBuffer的每个槽
fill(eventFactory);View on GitHub (pinned to 65f8d8beb7)