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

  1. Round the requested size up to the next power of 2 before constructing (e.g. Integer.highestOneBit(size - 1) << 1).
  2. Use a known-good size like 1024, 4096, or 8192 in your configuration.
  3. Validate/normalize user-supplied buffer-size config at startup with a clear message.
  4. 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

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


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)