On Tue, 13 Jan 2026 08:18:58 GMT, Alan Bateman <[email protected]> wrote:

> it would be useful to hear more on how this might be used

As an example, imagine a subclass which wants to add a fast `writeLong` method. 
With `ensureCapacity` available, this is as simple as:


public class LongStream extends ByteArrayOutputStream {

    private static final VarHandle LONG = 
MethodHandles.byteArrayViewVarHandle(long[].class, BIG_ENDIAN);

    public void writeLong(long value) {
        ensureCapacity(count + 8);
        LONG.set(buf, count, value);
        count += 8;
    }
}


Without access to `ensureCapacity`, having access only to the buffer and the 
count, the same class must copy the `ensureCapacity` logic, which means that it 
must also copy the `ArraysSupport.newLength` logic:


public class LongStream2 extends ByteArrayOutputStream {

    private static final VarHandle LONG = 
MethodHandles.byteArrayViewVarHandle(long[].class, BIG_ENDIAN);

    public void writeLong(long value) {
        ensureCapacity(count + 8);
        LONG.set(buf, count, value);
        count += 8;
    }

    // **************** copied from ByteArrayOutputStream ****************

    private void ensureCapacity(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = buf.length;
        int minGrowth = minCapacity - oldCapacity;
        if (minGrowth > 0) {
            buf = Arrays.copyOf(buf, /*ArraysSupport.*/newLength(oldCapacity,
                    minGrowth, oldCapacity /* preferred growth */));
        }
    }

    // ******************** copied from ArraysSupport ********************

    private static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;

    private static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        // preconditions not checked because of inlining
        // assert oldLength >= 0
        // assert minGrowth > 0

        int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might 
overflow
        if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
            return prefLength;
        } else {
            // put code cold in a separate method
            return hugeLength(oldLength, minGrowth);
        }
    }

    private static int hugeLength(int oldLength, int minGrowth) {
        int minLength = oldLength + minGrowth;
        if (minLength < 0) { // overflow
            throw new OutOfMemoryError(
                "Required array length " + oldLength + " + " + minGrowth + " is 
too large");
        } else if (minLength <= SOFT_MAX_ARRAY_LENGTH) {
            return SOFT_MAX_ARRAY_LENGTH;
        } else {
            return minLength;
        }
    }
}

-------------

PR Comment: https://git.openjdk.org/jdk/pull/29180#issuecomment-3743690145

Reply via email to